. auto/module
-njs_module_name=njs_crypto_module
-njs_module_incs=
-njs_module_srcs="external/njs_crypto_module.c \
- external/njs_md5.c \
- external/njs_sha1.c \
- external/njs_sha2.c"
+if [ $NJS_OPENSSL = YES -a $NJS_HAVE_OPENSSL = YES ]; then
+ njs_module_name=njs_crypto_module
+ njs_module_incs=
+ njs_module_srcs=external/njs_crypto_module.c
-. auto/module
+ . auto/module
-if [ $NJS_OPENSSL = YES -a $NJS_HAVE_OPENSSL = YES ]; then
njs_module_name=njs_webcrypto_module
njs_module_incs=
njs_module_srcs=external/njs_webcrypto_module.c
. auto/qjs_module
-njs_module_name=qjs_crypto_module
-njs_module_incs=
-njs_module_srcs=external/qjs_crypto_module.c
+if [ $NJS_OPENSSL = YES -a $NJS_HAVE_OPENSSL = YES ]; then
+ njs_module_name=qjs_crypto_module
+ njs_module_incs=
+ njs_module_srcs=external/qjs_crypto_module.c
-. auto/qjs_module
+ . auto/qjs_module
+fi
njs_module_name=qjs_fs_module
njs_module_incs=
#include <njs.h>
#include <njs_string.h>
#include <njs_buffer.h>
-#include "njs_hash.h"
+#include "njs_openssl.h"
-typedef void (*njs_hash_init)(njs_hash_t *ctx);
-typedef void (*njs_hash_update)(njs_hash_t *ctx, const void *data, size_t size);
-typedef void (*njs_hash_final)(u_char result[32], njs_hash_t *ctx);
-
typedef njs_int_t (*njs_digest_encode)(njs_vm_t *vm, njs_value_t *value,
const njs_str_t *src);
typedef struct {
- njs_str_t name;
-
- size_t size;
- njs_hash_init init;
- njs_hash_update update;
- njs_hash_final final;
-} njs_hash_alg_t;
-
-typedef struct {
- njs_hash_t ctx;
- njs_hash_alg_t *alg;
+ EVP_MD_CTX *ctx;
} njs_digest_t;
typedef struct {
- u_char opad[64];
- njs_hash_t ctx;
- njs_hash_alg_t *alg;
+ HMAC_CTX *ctx;
} njs_hmac_t;
typedef struct {
njs_str_t name;
-
njs_digest_encode encode;
} njs_crypto_enc_t;
-static njs_hash_alg_t *njs_crypto_algorithm(njs_vm_t *vm,
- njs_value_t *value);
-static njs_crypto_enc_t *njs_crypto_encoding(njs_vm_t *vm,
- njs_value_t *value);
+static const EVP_MD *njs_crypto_algorithm(njs_vm_t *vm, njs_value_t *value);
+static njs_crypto_enc_t *njs_crypto_encoding(njs_vm_t *vm, njs_value_t *value);
static njs_int_t njs_buffer_digest(njs_vm_t *vm, njs_value_t *value,
const njs_str_t *src);
static njs_int_t njs_crypto_create_hash(njs_vm_t *vm, njs_value_t *args,
static njs_int_t njs_crypto_create_hmac(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t unused, njs_value_t *retval);
-static njs_int_t njs_crypto_init(njs_vm_t *vm);
-
-
-static njs_hash_alg_t njs_hash_algorithms[] = {
-
- {
- njs_str("md5"),
- 16,
- njs_md5_init,
- njs_md5_update,
- njs_md5_final
- },
-
- {
- njs_str("sha1"),
- 20,
- njs_sha1_init,
- njs_sha1_update,
- njs_sha1_final
- },
-
- {
- njs_str("sha256"),
- 32,
- njs_sha2_init,
- njs_sha2_update,
- njs_sha2_final
- },
-
- {
- njs_null_str,
- 0,
- NULL,
- NULL,
- NULL
- }
+static void njs_crypto_cleanup_digest(void *data);
+static void njs_crypto_cleanup_hmac(void *data);
-};
+static njs_int_t njs_crypto_init(njs_vm_t *vm);
static njs_crypto_enc_t njs_encodings[] = {
njs_crypto_create_hash(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused, njs_value_t *retval)
{
- njs_digest_t *dgst;
- njs_hash_alg_t *alg;
+ njs_digest_t *dgst;
+ const EVP_MD *md;
+ njs_mp_cleanup_t *cln;
- alg = njs_crypto_algorithm(vm, njs_arg(args, nargs, 1));
- if (njs_slow_path(alg == NULL)) {
+ md = njs_crypto_algorithm(vm, njs_arg(args, nargs, 1));
+ if (njs_slow_path(md == NULL)) {
return NJS_ERROR;
}
return NJS_ERROR;
}
- dgst->alg = alg;
+ dgst->ctx = njs_evp_md_ctx_new();
+ if (njs_slow_path(dgst->ctx == NULL)) {
+ njs_vm_memory_error(vm);
+ return NJS_ERROR;
+ }
- alg->init(&dgst->ctx);
+ cln = njs_mp_cleanup_add(njs_vm_memory_pool(vm), 0);
+ if (njs_slow_path(cln == NULL)) {
+ njs_evp_md_ctx_free(dgst->ctx);
+ njs_vm_memory_error(vm);
+ return NJS_ERROR;
+ }
+
+ cln->handler = njs_crypto_cleanup_digest;
+ cln->data = dgst;
+
+ if (EVP_DigestInit_ex(dgst->ctx, md, NULL) <= 0) {
+ njs_vm_internal_error(vm, "EVP_DigestInit_ex() failed");
+ return NJS_ERROR;
+ }
return njs_vm_external_create(vm, retval, njs_crypto_hash_proto_id,
dgst, 0);
return NJS_ERROR;
}
- if (njs_slow_path(dgst->alg == NULL)) {
+ if (njs_slow_path(dgst->ctx == NULL)) {
njs_vm_error(vm, "Digest already called");
return NJS_ERROR;
}
return NJS_ERROR;
}
- if (njs_slow_path(ctx->alg == NULL)) {
+ if (njs_slow_path(ctx->ctx == NULL)) {
njs_vm_error(vm, "Digest already called");
return NJS_ERROR;
}
}
if (!hmac) {
- dgst->alg->update(&dgst->ctx, data.start, data.length);
+ if (EVP_DigestUpdate(dgst->ctx, data.start, data.length) <= 0) {
+ njs_vm_internal_error(vm, "EVP_DigestUpdate() failed");
+ return NJS_ERROR;
+ }
} else {
- ctx->alg->update(&ctx->ctx, data.start, data.length);
+ if (HMAC_Update(ctx->ctx, data.start, data.length) <= 0) {
+ njs_vm_internal_error(vm, "HMAC_Update() failed");
+ return NJS_ERROR;
+ }
}
njs_value_assign(retval, this);
njs_hmac_t *ctx;
njs_value_t *this;
njs_digest_t *dgst;
- njs_hash_alg_t *alg;
+ unsigned int len;
njs_crypto_enc_t *enc;
- u_char hash1[32], digest[32];
+ u_char digest[EVP_MAX_MD_SIZE];
this = njs_argument(args, 0);
return NJS_ERROR;
}
- if (njs_slow_path(dgst->alg == NULL)) {
+ if (njs_slow_path(dgst->ctx == NULL)) {
goto exception;
}
return NJS_ERROR;
}
- if (njs_slow_path(ctx->alg == NULL)) {
+ if (njs_slow_path(ctx->ctx == NULL)) {
goto exception;
}
}
if (!hmac) {
- alg = dgst->alg;
- alg->final(digest, &dgst->ctx);
- dgst->alg = NULL;
+ if (EVP_DigestFinal_ex(dgst->ctx, digest, &len) <= 0) {
+ njs_vm_internal_error(vm, "EVP_DigestFinal_ex() failed");
+ return NJS_ERROR;
+ }
+
+ njs_evp_md_ctx_free(dgst->ctx);
+ dgst->ctx = NULL;
} else {
- alg = ctx->alg;
- alg->final(hash1, &ctx->ctx);
+ if (HMAC_Final(ctx->ctx, digest, &len) <= 0) {
+ njs_vm_internal_error(vm, "HMAC_Final() failed");
+ return NJS_ERROR;
+ }
- alg->init(&ctx->ctx);
- alg->update(&ctx->ctx, ctx->opad, 64);
- alg->update(&ctx->ctx, hash1, alg->size);
- alg->final(digest, &ctx->ctx);
- ctx->alg = NULL;
+ njs_hmac_ctx_free(ctx->ctx);
+ ctx->ctx = NULL;
}
str.start = digest;
- str.length = alg->size;
+ str.length = len;
return enc->encode(vm, retval, &str);
njs_hash_prototype_copy(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused, njs_value_t *retval)
{
- njs_digest_t *dgst, *copy;
+ njs_digest_t *dgst, *copy;
+ njs_mp_cleanup_t *cln;
dgst = njs_vm_external(vm, njs_crypto_hash_proto_id, njs_argument(args, 0));
if (njs_slow_path(dgst == NULL)) {
return NJS_ERROR;
}
- if (njs_slow_path(dgst->alg == NULL)) {
+ if (njs_slow_path(dgst->ctx == NULL)) {
njs_vm_error(vm, "Digest already called");
return NJS_ERROR;
}
return NJS_ERROR;
}
- memcpy(copy, dgst, sizeof(njs_digest_t));
+ copy->ctx = njs_evp_md_ctx_new();
+ if (njs_slow_path(copy->ctx == NULL)) {
+ njs_vm_memory_error(vm);
+ return NJS_ERROR;
+ }
+
+ cln = njs_mp_cleanup_add(njs_vm_memory_pool(vm), 0);
+ if (njs_slow_path(cln == NULL)) {
+ njs_evp_md_ctx_free(copy->ctx);
+ njs_vm_memory_error(vm);
+ return NJS_ERROR;
+ }
+
+ cln->handler = njs_crypto_cleanup_digest;
+ cln->data = copy;
+
+ if (EVP_MD_CTX_copy_ex(copy->ctx, dgst->ctx) <= 0) {
+ njs_vm_internal_error(vm, "EVP_MD_CTX_copy_ex() failed");
+ return NJS_ERROR;
+ }
return njs_vm_external_create(vm, retval,
njs_crypto_hash_proto_id, copy, 0);
{
njs_int_t ret;
njs_str_t key;
- njs_uint_t i;
njs_hmac_t *ctx;
njs_value_t *value;
- njs_hash_alg_t *alg;
+ const EVP_MD *md;
+ njs_mp_cleanup_t *cln;
njs_opaque_value_t result;
const njs_buffer_encoding_t *enc;
- u_char digest[32], key_buf[64];
- alg = njs_crypto_algorithm(vm, njs_arg(args, nargs, 1));
- if (njs_slow_path(alg == NULL)) {
+ md = njs_crypto_algorithm(vm, njs_arg(args, nargs, 1));
+ if (njs_slow_path(md == NULL)) {
return NJS_ERROR;
}
return NJS_ERROR;
}
- ctx->alg = alg;
-
- if (key.length > sizeof(key_buf)) {
- alg->init(&ctx->ctx);
- alg->update(&ctx->ctx, key.start, key.length);
- alg->final(digest, &ctx->ctx);
-
- memcpy(key_buf, digest, alg->size);
- njs_explicit_memzero(key_buf + alg->size, sizeof(key_buf) - alg->size);
-
- } else {
- memcpy(key_buf, key.start, key.length);
- njs_explicit_memzero(key_buf + key.length,
- sizeof(key_buf) - key.length);
+ ctx->ctx = njs_hmac_ctx_new();
+ if (njs_slow_path(ctx->ctx == NULL)) {
+ njs_vm_memory_error(vm);
+ return NJS_ERROR;
}
- for (i = 0; i < 64; i++) {
- ctx->opad[i] = key_buf[i] ^ 0x5c;
+ cln = njs_mp_cleanup_add(njs_vm_memory_pool(vm), 0);
+ if (njs_slow_path(cln == NULL)) {
+ njs_hmac_ctx_free(ctx->ctx);
+ njs_vm_memory_error(vm);
+ return NJS_ERROR;
}
- for (i = 0; i < 64; i++) {
- key_buf[i] ^= 0x36;
- }
+ cln->handler = njs_crypto_cleanup_hmac;
+ cln->data = ctx;
- alg->init(&ctx->ctx);
- alg->update(&ctx->ctx, key_buf, 64);
+ if (HMAC_Init_ex(ctx->ctx, key.start, (int) key.length, md, NULL) <= 0) {
+ njs_vm_internal_error(vm, "HMAC_Init_ex() failed");
+ return NJS_ERROR;
+ }
return njs_vm_external_create(vm, retval, njs_crypto_hmac_proto_id,
ctx, 0);
}
-static njs_hash_alg_t *
+static const EVP_MD *
njs_crypto_algorithm(njs_vm_t *vm, njs_value_t *value)
{
- njs_str_t name;
- njs_hash_alg_t *e;
+ njs_str_t name;
+ const EVP_MD *md;
if (njs_slow_path(!njs_value_is_string(value))) {
njs_vm_type_error(vm, "algorithm must be a string");
njs_value_string_get(vm, value, &name);
- for (e = &njs_hash_algorithms[0]; e->name.length != 0; e++) {
- if (njs_strstr_eq(&name, &e->name)) {
- return e;
- }
+ if (njs_slow_path(njs_strlen(name.start) != name.length)) {
+ njs_vm_type_error(vm, "not supported algorithm: \"%V\"", &name);
+ return NULL;
}
- njs_vm_type_error(vm, "not supported algorithm: \"%V\"", &name);
+ md = EVP_get_digestbyname((const char *) name.start);
+ if (njs_slow_path(md == NULL)) {
+ njs_vm_type_error(vm, "not supported algorithm: \"%V\"", &name);
+ return NULL;
+ }
- return NULL;
+ return md;
}
}
+static void
+njs_crypto_cleanup_digest(void *data)
+{
+ njs_digest_t *dgst = data;
+
+ if (dgst->ctx != NULL) {
+ njs_evp_md_ctx_free(dgst->ctx);
+ dgst->ctx = NULL;
+ }
+}
+
+
+static void
+njs_crypto_cleanup_hmac(void *data)
+{
+ njs_hmac_t *ctx = data;
+
+ if (ctx->ctx != NULL) {
+ njs_hmac_ctx_free(ctx->ctx);
+ ctx->ctx = NULL;
+ }
+}
+
+
static njs_int_t
njs_crypto_init(njs_vm_t *vm)
{
+++ /dev/null
-
-/*
- * Copyright (C) Dmitry Volyntsev
- * Copyright (C) NGINX, Inc.
- */
-
-
-#ifndef _NJS_HASH_H_INCLUDED_
-#define _NJS_HASH_H_INCLUDED_
-
-
-typedef struct {
- uint64_t bytes;
- uint32_t a, b, c, d, e, f, g, h;
- u_char buffer[64];
-} njs_hash_t;
-
-
-NJS_EXPORT void njs_md5_init(njs_hash_t *ctx);
-NJS_EXPORT void njs_md5_update(njs_hash_t *ctx, const void *data, size_t size);
-NJS_EXPORT void njs_md5_final(u_char result[32], njs_hash_t *ctx);
-
-NJS_EXPORT void njs_sha1_init(njs_hash_t *ctx);
-NJS_EXPORT void njs_sha1_update(njs_hash_t *ctx, const void *data, size_t size);
-NJS_EXPORT void njs_sha1_final(u_char result[32], njs_hash_t *ctx);
-
-NJS_EXPORT void njs_sha2_init(njs_hash_t *ctx);
-NJS_EXPORT void njs_sha2_update(njs_hash_t *ctx, const void *data, size_t size);
-NJS_EXPORT void njs_sha2_final(u_char result[32], njs_hash_t *ctx);
-
-
-#endif /* _NJS_HASH_H_INCLUDED_ */
+++ /dev/null
-
-/*
- * An internal implementation, based on Alexander Peslyak's
- * public domain implementation:
- * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
- */
-
-
-#include <njs_unix.h>
-#include <njs_types.h>
-#include <njs_clang.h>
-#include <njs_str.h>
-#include "njs_hash.h"
-
-
-static const u_char *njs_md5_body(njs_hash_t *ctx, const u_char *data,
- size_t size);
-
-
-void
-njs_md5_init(njs_hash_t *ctx)
-{
- ctx->a = 0x67452301;
- ctx->b = 0xefcdab89;
- ctx->c = 0x98badcfe;
- ctx->d = 0x10325476;
-
- ctx->bytes = 0;
-}
-
-
-void
-njs_md5_update(njs_hash_t *ctx, const void *data, size_t size)
-{
- size_t used, free;
-
- used = (size_t) (ctx->bytes & 0x3f);
- ctx->bytes += size;
-
- if (used) {
- free = 64 - used;
-
- if (size < free) {
- memcpy(&ctx->buffer[used], data, size);
- return;
- }
-
- memcpy(&ctx->buffer[used], data, free);
- data = (u_char *) data + free;
- size -= free;
- (void) njs_md5_body(ctx, ctx->buffer, 64);
- }
-
- if (size >= 64) {
- data = njs_md5_body(ctx, data, size & ~(size_t) 0x3f);
- size &= 0x3f;
- }
-
- memcpy(ctx->buffer, data, size);
-}
-
-
-void
-njs_md5_final(u_char result[32], njs_hash_t *ctx)
-{
- size_t used, free;
-
- used = (size_t) (ctx->bytes & 0x3f);
-
- ctx->buffer[used++] = 0x80;
-
- free = 64 - used;
-
- if (free < 8) {
- njs_memzero(&ctx->buffer[used], free);
- (void) njs_md5_body(ctx, ctx->buffer, 64);
- used = 0;
- free = 64;
- }
-
- njs_memzero(&ctx->buffer[used], free - 8);
-
- ctx->bytes <<= 3;
- ctx->buffer[56] = (u_char) ctx->bytes;
- ctx->buffer[57] = (u_char) (ctx->bytes >> 8);
- ctx->buffer[58] = (u_char) (ctx->bytes >> 16);
- ctx->buffer[59] = (u_char) (ctx->bytes >> 24);
- ctx->buffer[60] = (u_char) (ctx->bytes >> 32);
- ctx->buffer[61] = (u_char) (ctx->bytes >> 40);
- ctx->buffer[62] = (u_char) (ctx->bytes >> 48);
- ctx->buffer[63] = (u_char) (ctx->bytes >> 56);
-
- (void) njs_md5_body(ctx, ctx->buffer, 64);
-
- result[0] = (u_char) ctx->a;
- result[1] = (u_char) (ctx->a >> 8);
- result[2] = (u_char) (ctx->a >> 16);
- result[3] = (u_char) (ctx->a >> 24);
- result[4] = (u_char) ctx->b;
- result[5] = (u_char) (ctx->b >> 8);
- result[6] = (u_char) (ctx->b >> 16);
- result[7] = (u_char) (ctx->b >> 24);
- result[8] = (u_char) ctx->c;
- result[9] = (u_char) (ctx->c >> 8);
- result[10] = (u_char) (ctx->c >> 16);
- result[11] = (u_char) (ctx->c >> 24);
- result[12] = (u_char) ctx->d;
- result[13] = (u_char) (ctx->d >> 8);
- result[14] = (u_char) (ctx->d >> 16);
- result[15] = (u_char) (ctx->d >> 24);
-
- njs_explicit_memzero(ctx, sizeof(*ctx));
-}
-
-
-/*
- * The basic MD5 functions.
- *
- * F and G are optimized compared to their RFC 1321 definitions for
- * architectures that lack an AND-NOT instruction, just like in
- * Colin Plumb's implementation.
- */
-
-#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
-#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define I(x, y, z) ((y) ^ ((x) | ~(z)))
-
-/*
- * The MD5 transformation for all four rounds.
- */
-
-#define STEP(f, a, b, c, d, x, t, s) \
- (a) += f((b), (c), (d)) + (x) + (t); \
- (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
- (a) += (b)
-
-/*
- * SET() reads 4 input bytes in little-endian byte order and stores them
- * in a properly aligned word in host byte order.
- */
-
-#define SET(n) \
- (block[n] = \
- ( (uint32_t) p[n * 4] \
- | ((uint32_t) p[n * 4 + 1] << 8) \
- | ((uint32_t) p[n * 4 + 2] << 16) \
- | ((uint32_t) p[n * 4 + 3] << 24))) \
-
-#define GET(n) block[n]
-
-
-/*
- * This processes one or more 64-byte data blocks, but does not update
- * the bit counters. There are no alignment requirements.
- */
-
-static const u_char *
-njs_md5_body(njs_hash_t *ctx, const u_char *data, size_t size)
-{
- uint32_t a, b, c, d;
- uint32_t saved_a, saved_b, saved_c, saved_d;
- const u_char *p;
- uint32_t block[16];
-
- p = data;
-
- a = ctx->a;
- b = ctx->b;
- c = ctx->c;
- d = ctx->d;
-
- do {
- saved_a = a;
- saved_b = b;
- saved_c = c;
- saved_d = d;
-
- /* Round 1 */
-
- STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7);
- STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12);
- STEP(F, c, d, a, b, SET(2), 0x242070db, 17);
- STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22);
- STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7);
- STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12);
- STEP(F, c, d, a, b, SET(6), 0xa8304613, 17);
- STEP(F, b, c, d, a, SET(7), 0xfd469501, 22);
- STEP(F, a, b, c, d, SET(8), 0x698098d8, 7);
- STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12);
- STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17);
- STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22);
- STEP(F, a, b, c, d, SET(12), 0x6b901122, 7);
- STEP(F, d, a, b, c, SET(13), 0xfd987193, 12);
- STEP(F, c, d, a, b, SET(14), 0xa679438e, 17);
- STEP(F, b, c, d, a, SET(15), 0x49b40821, 22);
-
- /* Round 2 */
-
- STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5);
- STEP(G, d, a, b, c, GET(6), 0xc040b340, 9);
- STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14);
- STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20);
- STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5);
- STEP(G, d, a, b, c, GET(10), 0x02441453, 9);
- STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14);
- STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20);
- STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5);
- STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9);
- STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14);
- STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20);
- STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5);
- STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9);
- STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14);
- STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20);
-
- /* Round 3 */
-
- STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4);
- STEP(H, d, a, b, c, GET(8), 0x8771f681, 11);
- STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16);
- STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23);
- STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4);
- STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11);
- STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16);
- STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23);
- STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4);
- STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11);
- STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16);
- STEP(H, b, c, d, a, GET(6), 0x04881d05, 23);
- STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4);
- STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11);
- STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16);
- STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23);
-
- /* Round 4 */
-
- STEP(I, a, b, c, d, GET(0), 0xf4292244, 6);
- STEP(I, d, a, b, c, GET(7), 0x432aff97, 10);
- STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15);
- STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21);
- STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6);
- STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10);
- STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15);
- STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21);
- STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6);
- STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10);
- STEP(I, c, d, a, b, GET(6), 0xa3014314, 15);
- STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21);
- STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6);
- STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10);
- STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15);
- STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21);
-
- a += saved_a;
- b += saved_b;
- c += saved_c;
- d += saved_d;
-
- p += 64;
-
- } while (size -= 64);
-
- ctx->a = a;
- ctx->b = b;
- ctx->c = c;
- ctx->d = d;
-
- return p;
-}
#endif
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+#define njs_hmac_ctx_new() HMAC_CTX_new()
+#define njs_hmac_ctx_free(_ctx) HMAC_CTX_free(_ctx)
+#else
+
+njs_inline HMAC_CTX *
+njs_hmac_ctx_new(void)
+{
+ HMAC_CTX *ctx;
+
+ ctx = OPENSSL_malloc(sizeof(HMAC_CTX));
+ if (ctx != NULL) {
+ HMAC_CTX_init(ctx);
+ }
+
+ return ctx;
+}
+
+
+njs_inline void
+njs_hmac_ctx_free(HMAC_CTX *ctx)
+{
+ if (ctx != NULL) {
+ HMAC_CTX_cleanup(ctx);
+ OPENSSL_free(ctx);
+ }
+}
+
+#endif
+
+
#define njs_bio_new_mem_buf(b, len) BIO_new_mem_buf((void *) b, len)
+++ /dev/null
-
-/*
- * Copyright (C) Maxim Dounin
- * Copyright (C) NGINX, Inc.
- *
- * An internal SHA1 implementation.
- */
-
-
-#include <njs_unix.h>
-#include <njs_types.h>
-#include <njs_clang.h>
-#include <njs_str.h>
-#include "njs_hash.h"
-
-
-static const u_char *njs_sha1_body(njs_hash_t *ctx, const u_char *data,
- size_t size);
-
-
-void
-njs_sha1_init(njs_hash_t *ctx)
-{
- ctx->a = 0x67452301;
- ctx->b = 0xefcdab89;
- ctx->c = 0x98badcfe;
- ctx->d = 0x10325476;
- ctx->e = 0xc3d2e1f0;
-
- ctx->bytes = 0;
-}
-
-
-void
-njs_sha1_update(njs_hash_t *ctx, const void *data, size_t size)
-{
- size_t used, free;
-
- used = (size_t) (ctx->bytes & 0x3f);
- ctx->bytes += size;
-
- if (used) {
- free = 64 - used;
-
- if (size < free) {
- memcpy(&ctx->buffer[used], data, size);
- return;
- }
-
- memcpy(&ctx->buffer[used], data, free);
- data = (u_char *) data + free;
- size -= free;
- (void) njs_sha1_body(ctx, ctx->buffer, 64);
- }
-
- if (size >= 64) {
- data = njs_sha1_body(ctx, data, size & ~(size_t) 0x3f);
- size &= 0x3f;
- }
-
- memcpy(ctx->buffer, data, size);
-}
-
-
-void
-njs_sha1_final(u_char result[32], njs_hash_t *ctx)
-{
- size_t used, free;
-
- used = (size_t) (ctx->bytes & 0x3f);
-
- ctx->buffer[used++] = 0x80;
-
- free = 64 - used;
-
- if (free < 8) {
- njs_memzero(&ctx->buffer[used], free);
- (void) njs_sha1_body(ctx, ctx->buffer, 64);
- used = 0;
- free = 64;
- }
-
- njs_memzero(&ctx->buffer[used], free - 8);
-
- ctx->bytes <<= 3;
- ctx->buffer[56] = (u_char) (ctx->bytes >> 56);
- ctx->buffer[57] = (u_char) (ctx->bytes >> 48);
- ctx->buffer[58] = (u_char) (ctx->bytes >> 40);
- ctx->buffer[59] = (u_char) (ctx->bytes >> 32);
- ctx->buffer[60] = (u_char) (ctx->bytes >> 24);
- ctx->buffer[61] = (u_char) (ctx->bytes >> 16);
- ctx->buffer[62] = (u_char) (ctx->bytes >> 8);
- ctx->buffer[63] = (u_char) ctx->bytes;
-
- (void) njs_sha1_body(ctx, ctx->buffer, 64);
-
- result[0] = (u_char) (ctx->a >> 24);
- result[1] = (u_char) (ctx->a >> 16);
- result[2] = (u_char) (ctx->a >> 8);
- result[3] = (u_char) ctx->a;
- result[4] = (u_char) (ctx->b >> 24);
- result[5] = (u_char) (ctx->b >> 16);
- result[6] = (u_char) (ctx->b >> 8);
- result[7] = (u_char) ctx->b;
- result[8] = (u_char) (ctx->c >> 24);
- result[9] = (u_char) (ctx->c >> 16);
- result[10] = (u_char) (ctx->c >> 8);
- result[11] = (u_char) ctx->c;
- result[12] = (u_char) (ctx->d >> 24);
- result[13] = (u_char) (ctx->d >> 16);
- result[14] = (u_char) (ctx->d >> 8);
- result[15] = (u_char) ctx->d;
- result[16] = (u_char) (ctx->e >> 24);
- result[17] = (u_char) (ctx->e >> 16);
- result[18] = (u_char) (ctx->e >> 8);
- result[19] = (u_char) ctx->e;
-
- njs_explicit_memzero(ctx, sizeof(*ctx));
-}
-
-
-/*
- * Helper functions.
- */
-
-#define ROTATE(bits, word) (((word) << (bits)) | ((word) >> (32 - (bits))))
-
-#define F1(b, c, d) (((b) & (c)) | ((~(b)) & (d)))
-#define F2(b, c, d) ((b) ^ (c) ^ (d))
-#define F3(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
-
-#define STEP(f, a, b, c, d, e, w, t) \
- temp = ROTATE(5, (a)) + f((b), (c), (d)) + (e) + (w) + (t); \
- (e) = (d); \
- (d) = (c); \
- (c) = ROTATE(30, (b)); \
- (b) = (a); \
- (a) = temp;
-
-
-/*
- * GET() reads 4 input bytes in big-endian byte order and returns
- * them as uint32_t.
- */
-
-#define GET(n) \
- ( ((uint32_t) p[n * 4 + 3]) \
- | ((uint32_t) p[n * 4 + 2] << 8) \
- | ((uint32_t) p[n * 4 + 1] << 16) \
- | ((uint32_t) p[n * 4] << 24))
-
-
-/*
- * This processes one or more 64-byte data blocks, but does not update
- * the bit counters. There are no alignment requirements.
- */
-
-static const u_char *
-njs_sha1_body(njs_hash_t *ctx, const u_char *data, size_t size)
-{
- uint32_t a, b, c, d, e, temp;
- uint32_t saved_a, saved_b, saved_c, saved_d, saved_e;
- uint32_t words[80];
- njs_uint_t i;
- const u_char *p;
-
- p = data;
-
- a = ctx->a;
- b = ctx->b;
- c = ctx->c;
- d = ctx->d;
- e = ctx->e;
-
- do {
- saved_a = a;
- saved_b = b;
- saved_c = c;
- saved_d = d;
- saved_e = e;
-
- /* Load data block into the words array */
-
- for (i = 0; i < 16; i++) {
- words[i] = GET(i);
- }
-
- for (i = 16; i < 80; i++) {
- words[i] = ROTATE(1, words[i - 3]
- ^ words[i - 8]
- ^ words[i - 14]
- ^ words[i - 16]);
- }
-
- /* Transformations */
-
- STEP(F1, a, b, c, d, e, words[0], 0x5a827999);
- STEP(F1, a, b, c, d, e, words[1], 0x5a827999);
- STEP(F1, a, b, c, d, e, words[2], 0x5a827999);
- STEP(F1, a, b, c, d, e, words[3], 0x5a827999);
- STEP(F1, a, b, c, d, e, words[4], 0x5a827999);
- STEP(F1, a, b, c, d, e, words[5], 0x5a827999);
- STEP(F1, a, b, c, d, e, words[6], 0x5a827999);
- STEP(F1, a, b, c, d, e, words[7], 0x5a827999);
- STEP(F1, a, b, c, d, e, words[8], 0x5a827999);
- STEP(F1, a, b, c, d, e, words[9], 0x5a827999);
- STEP(F1, a, b, c, d, e, words[10], 0x5a827999);
- STEP(F1, a, b, c, d, e, words[11], 0x5a827999);
- STEP(F1, a, b, c, d, e, words[12], 0x5a827999);
- STEP(F1, a, b, c, d, e, words[13], 0x5a827999);
- STEP(F1, a, b, c, d, e, words[14], 0x5a827999);
- STEP(F1, a, b, c, d, e, words[15], 0x5a827999);
- STEP(F1, a, b, c, d, e, words[16], 0x5a827999);
- STEP(F1, a, b, c, d, e, words[17], 0x5a827999);
- STEP(F1, a, b, c, d, e, words[18], 0x5a827999);
- STEP(F1, a, b, c, d, e, words[19], 0x5a827999);
-
- STEP(F2, a, b, c, d, e, words[20], 0x6ed9eba1);
- STEP(F2, a, b, c, d, e, words[21], 0x6ed9eba1);
- STEP(F2, a, b, c, d, e, words[22], 0x6ed9eba1);
- STEP(F2, a, b, c, d, e, words[23], 0x6ed9eba1);
- STEP(F2, a, b, c, d, e, words[24], 0x6ed9eba1);
- STEP(F2, a, b, c, d, e, words[25], 0x6ed9eba1);
- STEP(F2, a, b, c, d, e, words[26], 0x6ed9eba1);
- STEP(F2, a, b, c, d, e, words[27], 0x6ed9eba1);
- STEP(F2, a, b, c, d, e, words[28], 0x6ed9eba1);
- STEP(F2, a, b, c, d, e, words[29], 0x6ed9eba1);
- STEP(F2, a, b, c, d, e, words[30], 0x6ed9eba1);
- STEP(F2, a, b, c, d, e, words[31], 0x6ed9eba1);
- STEP(F2, a, b, c, d, e, words[32], 0x6ed9eba1);
- STEP(F2, a, b, c, d, e, words[33], 0x6ed9eba1);
- STEP(F2, a, b, c, d, e, words[34], 0x6ed9eba1);
- STEP(F2, a, b, c, d, e, words[35], 0x6ed9eba1);
- STEP(F2, a, b, c, d, e, words[36], 0x6ed9eba1);
- STEP(F2, a, b, c, d, e, words[37], 0x6ed9eba1);
- STEP(F2, a, b, c, d, e, words[38], 0x6ed9eba1);
- STEP(F2, a, b, c, d, e, words[39], 0x6ed9eba1);
-
- STEP(F3, a, b, c, d, e, words[40], 0x8f1bbcdc);
- STEP(F3, a, b, c, d, e, words[41], 0x8f1bbcdc);
- STEP(F3, a, b, c, d, e, words[42], 0x8f1bbcdc);
- STEP(F3, a, b, c, d, e, words[43], 0x8f1bbcdc);
- STEP(F3, a, b, c, d, e, words[44], 0x8f1bbcdc);
- STEP(F3, a, b, c, d, e, words[45], 0x8f1bbcdc);
- STEP(F3, a, b, c, d, e, words[46], 0x8f1bbcdc);
- STEP(F3, a, b, c, d, e, words[47], 0x8f1bbcdc);
- STEP(F3, a, b, c, d, e, words[48], 0x8f1bbcdc);
- STEP(F3, a, b, c, d, e, words[49], 0x8f1bbcdc);
- STEP(F3, a, b, c, d, e, words[50], 0x8f1bbcdc);
- STEP(F3, a, b, c, d, e, words[51], 0x8f1bbcdc);
- STEP(F3, a, b, c, d, e, words[52], 0x8f1bbcdc);
- STEP(F3, a, b, c, d, e, words[53], 0x8f1bbcdc);
- STEP(F3, a, b, c, d, e, words[54], 0x8f1bbcdc);
- STEP(F3, a, b, c, d, e, words[55], 0x8f1bbcdc);
- STEP(F3, a, b, c, d, e, words[56], 0x8f1bbcdc);
- STEP(F3, a, b, c, d, e, words[57], 0x8f1bbcdc);
- STEP(F3, a, b, c, d, e, words[58], 0x8f1bbcdc);
- STEP(F3, a, b, c, d, e, words[59], 0x8f1bbcdc);
-
- STEP(F2, a, b, c, d, e, words[60], 0xca62c1d6);
- STEP(F2, a, b, c, d, e, words[61], 0xca62c1d6);
- STEP(F2, a, b, c, d, e, words[62], 0xca62c1d6);
- STEP(F2, a, b, c, d, e, words[63], 0xca62c1d6);
- STEP(F2, a, b, c, d, e, words[64], 0xca62c1d6);
- STEP(F2, a, b, c, d, e, words[65], 0xca62c1d6);
- STEP(F2, a, b, c, d, e, words[66], 0xca62c1d6);
- STEP(F2, a, b, c, d, e, words[67], 0xca62c1d6);
- STEP(F2, a, b, c, d, e, words[68], 0xca62c1d6);
- STEP(F2, a, b, c, d, e, words[69], 0xca62c1d6);
- STEP(F2, a, b, c, d, e, words[70], 0xca62c1d6);
- STEP(F2, a, b, c, d, e, words[71], 0xca62c1d6);
- STEP(F2, a, b, c, d, e, words[72], 0xca62c1d6);
- STEP(F2, a, b, c, d, e, words[73], 0xca62c1d6);
- STEP(F2, a, b, c, d, e, words[74], 0xca62c1d6);
- STEP(F2, a, b, c, d, e, words[75], 0xca62c1d6);
- STEP(F2, a, b, c, d, e, words[76], 0xca62c1d6);
- STEP(F2, a, b, c, d, e, words[77], 0xca62c1d6);
- STEP(F2, a, b, c, d, e, words[78], 0xca62c1d6);
- STEP(F2, a, b, c, d, e, words[79], 0xca62c1d6);
-
- a += saved_a;
- b += saved_b;
- c += saved_c;
- d += saved_d;
- e += saved_e;
-
- p += 64;
-
- } while (size -= 64);
-
- ctx->a = a;
- ctx->b = b;
- ctx->c = c;
- ctx->d = d;
- ctx->e = e;
-
- return p;
-}
+++ /dev/null
-
-/*
- * Copyright (C) Dmitry Volyntsev
- * Copyright (C) NGINX, Inc.
- *
- * An internal SHA2 implementation.
- */
-
-
-#include <njs_unix.h>
-#include <njs_types.h>
-#include <njs_clang.h>
-#include <njs_str.h>
-#include "njs_hash.h"
-
-
-static const u_char *njs_sha2_body(njs_hash_t *ctx, const u_char *data,
- size_t size);
-
-
-void
-njs_sha2_init(njs_hash_t *ctx)
-{
- ctx->a = 0x6a09e667;
- ctx->b = 0xbb67ae85;
- ctx->c = 0x3c6ef372;
- ctx->d = 0xa54ff53a;
- ctx->e = 0x510e527f;
- ctx->f = 0x9b05688c;
- ctx->g = 0x1f83d9ab;
- ctx->h = 0x5be0cd19;
-
- ctx->bytes = 0;
-}
-
-
-void
-njs_sha2_update(njs_hash_t *ctx, const void *data, size_t size)
-{
- size_t used, free;
-
- used = (size_t) (ctx->bytes & 0x3f);
- ctx->bytes += size;
-
- if (used) {
- free = 64 - used;
-
- if (size < free) {
- memcpy(&ctx->buffer[used], data, size);
- return;
- }
-
- memcpy(&ctx->buffer[used], data, free);
- data = (u_char *) data + free;
- size -= free;
- (void) njs_sha2_body(ctx, ctx->buffer, 64);
- }
-
- if (size >= 64) {
- data = njs_sha2_body(ctx, data, size & ~(size_t) 0x3f);
- size &= 0x3f;
- }
-
- memcpy(ctx->buffer, data, size);
-}
-
-
-void
-njs_sha2_final(u_char result[32], njs_hash_t *ctx)
-{
- size_t used, free;
-
- used = (size_t) (ctx->bytes & 0x3f);
-
- ctx->buffer[used++] = 0x80;
-
- free = 64 - used;
-
- if (free < 8) {
- njs_memzero(&ctx->buffer[used], free);
- (void) njs_sha2_body(ctx, ctx->buffer, 64);
- used = 0;
- free = 64;
- }
-
- njs_memzero(&ctx->buffer[used], free - 8);
-
- ctx->bytes <<= 3;
- ctx->buffer[56] = (u_char) (ctx->bytes >> 56);
- ctx->buffer[57] = (u_char) (ctx->bytes >> 48);
- ctx->buffer[58] = (u_char) (ctx->bytes >> 40);
- ctx->buffer[59] = (u_char) (ctx->bytes >> 32);
- ctx->buffer[60] = (u_char) (ctx->bytes >> 24);
- ctx->buffer[61] = (u_char) (ctx->bytes >> 16);
- ctx->buffer[62] = (u_char) (ctx->bytes >> 8);
- ctx->buffer[63] = (u_char) ctx->bytes;
-
- (void) njs_sha2_body(ctx, ctx->buffer, 64);
-
- result[0] = (u_char) (ctx->a >> 24);
- result[1] = (u_char) (ctx->a >> 16);
- result[2] = (u_char) (ctx->a >> 8);
- result[3] = (u_char) ctx->a;
- result[4] = (u_char) (ctx->b >> 24);
- result[5] = (u_char) (ctx->b >> 16);
- result[6] = (u_char) (ctx->b >> 8);
- result[7] = (u_char) ctx->b;
- result[8] = (u_char) (ctx->c >> 24);
- result[9] = (u_char) (ctx->c >> 16);
- result[10] = (u_char) (ctx->c >> 8);
- result[11] = (u_char) ctx->c;
- result[12] = (u_char) (ctx->d >> 24);
- result[13] = (u_char) (ctx->d >> 16);
- result[14] = (u_char) (ctx->d >> 8);
- result[15] = (u_char) ctx->d;
- result[16] = (u_char) (ctx->e >> 24);
- result[17] = (u_char) (ctx->e >> 16);
- result[18] = (u_char) (ctx->e >> 8);
- result[19] = (u_char) ctx->e;
- result[20] = (u_char) (ctx->f >> 24);
- result[21] = (u_char) (ctx->f >> 16);
- result[22] = (u_char) (ctx->f >> 8);
- result[23] = (u_char) ctx->f;
- result[24] = (u_char) (ctx->g >> 24);
- result[25] = (u_char) (ctx->g >> 16);
- result[26] = (u_char) (ctx->g >> 8);
- result[27] = (u_char) ctx->g;
- result[28] = (u_char) (ctx->h >> 24);
- result[29] = (u_char) (ctx->h >> 16);
- result[30] = (u_char) (ctx->h >> 8);
- result[31] = (u_char) ctx->h;
-
- njs_explicit_memzero(ctx, sizeof(*ctx));
-}
-
-
-/*
- * Helper functions.
- */
-
-#define ROTATE(bits, word) (((word) >> (bits)) | ((word) << (32 - (bits))))
-
-#define S0(a) (ROTATE(2, a) ^ ROTATE(13, a) ^ ROTATE(22, a))
-#define S1(e) (ROTATE(6, e) ^ ROTATE(11, e) ^ ROTATE(25, e))
-#define CH(e, f, g) (((e) & (f)) ^ ((~(e)) & (g)))
-#define MAJ(a, b, c) (((a) & (b)) ^ ((a) & (c)) ^ ((b) & (c)))
-
-#define STEP(a, b, c, d, e, f, g, h, w, k) \
- temp1 = (h) + S1(e) + CH(e, f, g) + (k) + (w); \
- temp2 = S0(a) + MAJ(a, b, c); \
- (h) = (g); \
- (g) = (f); \
- (f) = (e); \
- (e) = (d) + temp1; \
- (d) = (c); \
- (c) = (b); \
- (b) = (a); \
- (a) = temp1 + temp2;
-
-
-/*
- * GET() reads 4 input bytes in big-endian byte order and returns
- * them as uint32_t.
- */
-
-#define GET(n) \
- ( ((uint32_t) p[n * 4 + 3]) \
- | ((uint32_t) p[n * 4 + 2] << 8) \
- | ((uint32_t) p[n * 4 + 1] << 16) \
- | ((uint32_t) p[n * 4] << 24))
-
-
-/*
- * This processes one or more 64-byte data blocks, but does not update
- * the bit counters. There are no alignment requirements.
- */
-
-static const u_char *
-njs_sha2_body(njs_hash_t *ctx, const u_char *data, size_t size)
-{
- uint32_t a, b, c, d, e, f, g, h, s0, s1, temp1, temp2;
- uint32_t saved_a, saved_b, saved_c, saved_d, saved_e, saved_f,
- saved_g, saved_h;
- uint32_t words[64];
- njs_uint_t i;
- const u_char *p;
-
- p = data;
-
- a = ctx->a;
- b = ctx->b;
- c = ctx->c;
- d = ctx->d;
- e = ctx->e;
- f = ctx->f;
- g = ctx->g;
- h = ctx->h;
-
- do {
- saved_a = a;
- saved_b = b;
- saved_c = c;
- saved_d = d;
- saved_e = e;
- saved_f = f;
- saved_g = g;
- saved_h = h;
-
- /* Load data block into the words array */
-
- for (i = 0; i < 16; i++) {
- words[i] = GET(i);
- }
-
- for (i = 16; i < 64; i++) {
- s0 = ROTATE(7, words[i - 15])
- ^ ROTATE(18, words[i - 15])
- ^ (words[i - 15] >> 3);
-
- s1 = ROTATE(17, words[i - 2])
- ^ ROTATE(19, words[i - 2])
- ^ (words[i - 2] >> 10);
-
- words[i] = words[i - 16] + s0 + words[i - 7] + s1;
- }
-
- /* Transformations */
-
- STEP(a, b, c, d, e, f, g, h, words[0], 0x428a2f98);
- STEP(a, b, c, d, e, f, g, h, words[1], 0x71374491);
- STEP(a, b, c, d, e, f, g, h, words[2], 0xb5c0fbcf);
- STEP(a, b, c, d, e, f, g, h, words[3], 0xe9b5dba5);
- STEP(a, b, c, d, e, f, g, h, words[4], 0x3956c25b);
- STEP(a, b, c, d, e, f, g, h, words[5], 0x59f111f1);
- STEP(a, b, c, d, e, f, g, h, words[6], 0x923f82a4);
- STEP(a, b, c, d, e, f, g, h, words[7], 0xab1c5ed5);
- STEP(a, b, c, d, e, f, g, h, words[8], 0xd807aa98);
- STEP(a, b, c, d, e, f, g, h, words[9], 0x12835b01);
- STEP(a, b, c, d, e, f, g, h, words[10], 0x243185be);
- STEP(a, b, c, d, e, f, g, h, words[11], 0x550c7dc3);
- STEP(a, b, c, d, e, f, g, h, words[12], 0x72be5d74);
- STEP(a, b, c, d, e, f, g, h, words[13], 0x80deb1fe);
- STEP(a, b, c, d, e, f, g, h, words[14], 0x9bdc06a7);
- STEP(a, b, c, d, e, f, g, h, words[15], 0xc19bf174);
-
- STEP(a, b, c, d, e, f, g, h, words[16], 0xe49b69c1);
- STEP(a, b, c, d, e, f, g, h, words[17], 0xefbe4786);
- STEP(a, b, c, d, e, f, g, h, words[18], 0x0fc19dc6);
- STEP(a, b, c, d, e, f, g, h, words[19], 0x240ca1cc);
- STEP(a, b, c, d, e, f, g, h, words[20], 0x2de92c6f);
- STEP(a, b, c, d, e, f, g, h, words[21], 0x4a7484aa);
- STEP(a, b, c, d, e, f, g, h, words[22], 0x5cb0a9dc);
- STEP(a, b, c, d, e, f, g, h, words[23], 0x76f988da);
- STEP(a, b, c, d, e, f, g, h, words[24], 0x983e5152);
- STEP(a, b, c, d, e, f, g, h, words[25], 0xa831c66d);
- STEP(a, b, c, d, e, f, g, h, words[26], 0xb00327c8);
- STEP(a, b, c, d, e, f, g, h, words[27], 0xbf597fc7);
- STEP(a, b, c, d, e, f, g, h, words[28], 0xc6e00bf3);
- STEP(a, b, c, d, e, f, g, h, words[29], 0xd5a79147);
- STEP(a, b, c, d, e, f, g, h, words[30], 0x06ca6351);
- STEP(a, b, c, d, e, f, g, h, words[31], 0x14292967);
-
- STEP(a, b, c, d, e, f, g, h, words[32], 0x27b70a85);
- STEP(a, b, c, d, e, f, g, h, words[33], 0x2e1b2138);
- STEP(a, b, c, d, e, f, g, h, words[34], 0x4d2c6dfc);
- STEP(a, b, c, d, e, f, g, h, words[35], 0x53380d13);
- STEP(a, b, c, d, e, f, g, h, words[36], 0x650a7354);
- STEP(a, b, c, d, e, f, g, h, words[37], 0x766a0abb);
- STEP(a, b, c, d, e, f, g, h, words[38], 0x81c2c92e);
- STEP(a, b, c, d, e, f, g, h, words[39], 0x92722c85);
- STEP(a, b, c, d, e, f, g, h, words[40], 0xa2bfe8a1);
- STEP(a, b, c, d, e, f, g, h, words[41], 0xa81a664b);
- STEP(a, b, c, d, e, f, g, h, words[42], 0xc24b8b70);
- STEP(a, b, c, d, e, f, g, h, words[43], 0xc76c51a3);
- STEP(a, b, c, d, e, f, g, h, words[44], 0xd192e819);
- STEP(a, b, c, d, e, f, g, h, words[45], 0xd6990624);
- STEP(a, b, c, d, e, f, g, h, words[46], 0xf40e3585);
- STEP(a, b, c, d, e, f, g, h, words[47], 0x106aa070);
-
- STEP(a, b, c, d, e, f, g, h, words[48], 0x19a4c116);
- STEP(a, b, c, d, e, f, g, h, words[49], 0x1e376c08);
- STEP(a, b, c, d, e, f, g, h, words[50], 0x2748774c);
- STEP(a, b, c, d, e, f, g, h, words[51], 0x34b0bcb5);
- STEP(a, b, c, d, e, f, g, h, words[52], 0x391c0cb3);
- STEP(a, b, c, d, e, f, g, h, words[53], 0x4ed8aa4a);
- STEP(a, b, c, d, e, f, g, h, words[54], 0x5b9cca4f);
- STEP(a, b, c, d, e, f, g, h, words[55], 0x682e6ff3);
- STEP(a, b, c, d, e, f, g, h, words[56], 0x748f82ee);
- STEP(a, b, c, d, e, f, g, h, words[57], 0x78a5636f);
- STEP(a, b, c, d, e, f, g, h, words[58], 0x84c87814);
- STEP(a, b, c, d, e, f, g, h, words[59], 0x8cc70208);
- STEP(a, b, c, d, e, f, g, h, words[60], 0x90befffa);
- STEP(a, b, c, d, e, f, g, h, words[61], 0xa4506ceb);
- STEP(a, b, c, d, e, f, g, h, words[62], 0xbef9a3f7);
- STEP(a, b, c, d, e, f, g, h, words[63], 0xc67178f2);
-
- a += saved_a;
- b += saved_b;
- c += saved_c;
- d += saved_d;
- e += saved_e;
- f += saved_f;
- g += saved_g;
- h += saved_h;
-
- p += 64;
-
- } while (size -= 64);
-
- ctx->a = a;
- ctx->b = b;
- ctx->c = c;
- ctx->d = d;
- ctx->e = e;
- ctx->f = f;
- ctx->g = g;
- ctx->h = h;
-
- return p;
-}
*/
#include <qjs.h>
-#include "njs_hash.h"
-
-typedef void (*qjs_hash_init)(njs_hash_t *ctx);
-typedef void (*qjs_hash_update)(njs_hash_t *ctx, const void *data, size_t size);
-typedef void (*qjs_hash_final)(u_char result[32], njs_hash_t *ctx);
+#include "njs_openssl.h"
typedef JSValue (*qjs_digest_encode)(JSContext *cx, const njs_str_t *src);
typedef struct {
- njs_str_t name;
-
- size_t size;
- qjs_hash_init init;
- qjs_hash_update update;
- qjs_hash_final final;
-} qjs_hash_alg_t;
-
-typedef struct {
- njs_hash_t ctx;
- qjs_hash_alg_t *alg;
+ EVP_MD_CTX *ctx;
} qjs_digest_t;
typedef struct {
- u_char opad[64];
- njs_hash_t ctx;
- qjs_hash_alg_t *alg;
+ HMAC_CTX *ctx;
} qjs_hmac_t;
} qjs_crypto_enc_t;
-static qjs_hash_alg_t *qjs_crypto_algorithm(JSContext *cx, JSValueConst val);
+static const EVP_MD *qjs_crypto_algorithm(JSContext *cx, JSValueConst val);
static qjs_crypto_enc_t *qjs_crypto_encoding(JSContext *cx, JSValueConst val);
static JSValue qjs_buffer_digest(JSContext *cx, const njs_str_t *src);
static JSValue qjs_crypto_create_hash(JSContext *cx, JSValueConst this_val,
static JSModuleDef * qjs_crypto_init(JSContext *cx, const char *module_name);
-static qjs_hash_alg_t qjs_hash_algorithms[] = {
-
- {
- njs_str("md5"),
- 16,
- njs_md5_init,
- njs_md5_update,
- njs_md5_final
- },
-
- {
- njs_str("sha1"),
- 20,
- njs_sha1_init,
- njs_sha1_update,
- njs_sha1_final
- },
-
- {
- njs_str("sha256"),
- 32,
- njs_sha2_init,
- njs_sha2_update,
- njs_sha2_final
- },
-
- {
- njs_null_str,
- 0,
- NULL,
- NULL,
- NULL
- }
-
-};
-
-
static qjs_crypto_enc_t qjs_encodings[] = {
{
qjs_crypto_create_hash(JSContext *cx, JSValueConst this_val, int argc,
JSValueConst *argv)
{
- JSValue obj;
- qjs_digest_t *dgst;
- qjs_hash_alg_t *alg;
+ JSValue obj;
+ qjs_digest_t *dgst;
+ const EVP_MD *md;
- alg = qjs_crypto_algorithm(cx, argv[0]);
- if (alg == NULL) {
+ md = qjs_crypto_algorithm(cx, argv[0]);
+ if (md == NULL) {
return JS_EXCEPTION;
}
return JS_ThrowOutOfMemory(cx);
}
- dgst->alg = alg;
- alg->init(&dgst->ctx);
+ dgst->ctx = njs_evp_md_ctx_new();
+ if (dgst->ctx == NULL) {
+ js_free(cx, dgst);
+ return JS_ThrowOutOfMemory(cx);
+ }
+
+ if (EVP_DigestInit_ex(dgst->ctx, md, NULL) <= 0) {
+ njs_evp_md_ctx_free(dgst->ctx);
+ js_free(cx, dgst);
+ JS_ThrowInternalError(cx, "EVP_DigestInit_ex() failed");
+ return JS_EXCEPTION;
+ }
obj = JS_NewObjectClass(cx, QJS_CORE_CLASS_CRYPTO_HASH);
if (JS_IsException(obj)) {
+ njs_evp_md_ctx_free(dgst->ctx);
js_free(cx, dgst);
return obj;
}
JSValueConst *argv, int hmac)
{
njs_str_t str, content;
- njs_hash_t *uctx;
qjs_hmac_t *hctx;
qjs_bytes_t bytes;
qjs_digest_t *dgst;
const qjs_buffer_encoding_t *enc;
- void (*update)(njs_hash_t *ctx, const void *data, size_t size);
-
if (!hmac) {
dgst = JS_GetOpaque2(cx, this_val, QJS_CORE_CLASS_CRYPTO_HASH);
if (dgst == NULL) {
return JS_ThrowTypeError(cx, "\"this\" is not a hash object");
}
- if (dgst->alg == NULL) {
+ if (dgst->ctx == NULL) {
return JS_ThrowTypeError(cx, "Digest already called");
}
- update = dgst->alg->update;
- uctx = &dgst->ctx;
+ hctx = NULL;
} else {
hctx = JS_GetOpaque2(cx, this_val, QJS_CORE_CLASS_CRYPTO_HMAC);
return JS_ThrowTypeError(cx, "\"this\" is not a hmac object");
}
- if (hctx->alg == NULL) {
+ if (hctx->ctx == NULL) {
return JS_ThrowTypeError(cx, "Digest already called");
}
- update = hctx->alg->update;
- uctx = &hctx->ctx;
+ dgst = NULL;
}
if (JS_IsString(argv[0])) {
if (enc->decode(cx, &str, &content) != 0) {
JS_FreeCString(cx, (const char *) str.start);
- JS_FreeCString(cx, (const char *) content.start);
+ js_free(cx, content.start);
return JS_EXCEPTION;
}
JS_FreeCString(cx, (const char *) str.start);
- update(uctx, content.start, content.length);
+ if (!hmac) {
+ if (EVP_DigestUpdate(dgst->ctx, content.start, content.length)
+ <= 0)
+ {
+ js_free(cx, content.start);
+ JS_ThrowInternalError(cx, "EVP_DigestUpdate() failed");
+ return JS_EXCEPTION;
+ }
+
+ } else {
+ if (HMAC_Update(hctx->ctx, content.start, content.length) <= 0)
+ {
+ js_free(cx, content.start);
+ JS_ThrowInternalError(cx, "HMAC_Update() failed");
+ return JS_EXCEPTION;
+ }
+ }
+
js_free(cx, content.start);
} else {
- update(uctx, str.start, str.length);
- JS_FreeCString(cx, (const char *) str.start);
+ if (!hmac) {
+ if (EVP_DigestUpdate(dgst->ctx, str.start, str.length) <= 0) {
+ JS_FreeCString(cx, (const char *) str.start);
+ JS_ThrowInternalError(cx, "EVP_DigestUpdate() failed");
+ return JS_EXCEPTION;
+ }
+
+ } else {
+ if (HMAC_Update(hctx->ctx, str.start, str.length) <= 0) {
+ JS_FreeCString(cx, (const char *) str.start);
+ JS_ThrowInternalError(cx, "HMAC_Update() failed");
+ return JS_EXCEPTION;
+ }
+ }
+
+ JS_FreeCString(cx, (const char *) str.start);
}
} else if (qjs_is_typed_array(cx, argv[0])) {
return JS_EXCEPTION;
}
- update(uctx, bytes.start, bytes.length);
+ if (!hmac) {
+ if (EVP_DigestUpdate(dgst->ctx, bytes.start, bytes.length) <= 0) {
+ JS_ThrowInternalError(cx, "EVP_DigestUpdate() failed");
+ return JS_EXCEPTION;
+ }
+
+ } else {
+ if (HMAC_Update(hctx->ctx, bytes.start, bytes.length) <= 0) {
+ JS_ThrowInternalError(cx, "HMAC_Update() failed");
+ return JS_EXCEPTION;
+ }
+ }
} else {
return JS_ThrowTypeError(cx,
JSValueConst *argv, int hmac)
{
njs_str_t str;
+ unsigned int len;
qjs_hmac_t *hctx;
qjs_digest_t *dgst;
- qjs_hash_alg_t *alg;
qjs_crypto_enc_t *enc;
- u_char hash1[32],digest[32];
+ u_char digest[EVP_MAX_MD_SIZE];
if (!hmac) {
dgst = JS_GetOpaque2(cx, this_val, QJS_CORE_CLASS_CRYPTO_HASH);
return JS_ThrowTypeError(cx, "\"this\" is not a hash object");
}
- alg = dgst->alg;
- if (alg == NULL) {
+ if (dgst->ctx == NULL) {
return JS_ThrowTypeError(cx, "Digest already called");
}
- dgst->alg = NULL;
+ if (EVP_DigestFinal_ex(dgst->ctx, digest, &len) <= 0) {
+ JS_ThrowInternalError(cx, "EVP_DigestFinal_ex() failed");
+ return JS_EXCEPTION;
+ }
- alg->final(digest, &dgst->ctx);
+ njs_evp_md_ctx_free(dgst->ctx);
+ dgst->ctx = NULL;
} else {
hctx = JS_GetOpaque2(cx, this_val, QJS_CORE_CLASS_CRYPTO_HMAC);
return JS_ThrowTypeError(cx, "\"this\" is not a hmac object");
}
- alg = hctx->alg;
- if (alg == NULL) {
+ if (hctx->ctx == NULL) {
return JS_ThrowTypeError(cx, "Digest already called");
}
- hctx->alg = NULL;
-
- alg->final(hash1, &hctx->ctx);
+ if (HMAC_Final(hctx->ctx, digest, &len) <= 0) {
+ JS_ThrowInternalError(cx, "HMAC_Final() failed");
+ return JS_EXCEPTION;
+ }
- alg->init(&hctx->ctx);
- alg->update(&hctx->ctx, hctx->opad, 64);
- alg->update(&hctx->ctx, hash1, alg->size);
- alg->final(digest, &hctx->ctx);
+ njs_hmac_ctx_free(hctx->ctx);
+ hctx->ctx = NULL;
}
str.start = digest;
- str.length = alg->size;
+ str.length = len;
if (argc == 0) {
return qjs_buffer_digest(cx, &str);
return JS_EXCEPTION;
}
- if (dgst->alg == NULL) {
+ if (dgst->ctx == NULL) {
return JS_ThrowTypeError(cx, "Digest already called");
}
return JS_ThrowOutOfMemory(cx);
}
- memcpy(copy, dgst, sizeof(qjs_digest_t));
+ copy->ctx = njs_evp_md_ctx_new();
+ if (copy->ctx == NULL) {
+ js_free(cx, copy);
+ return JS_ThrowOutOfMemory(cx);
+ }
+
+ if (EVP_MD_CTX_copy_ex(copy->ctx, dgst->ctx) <= 0) {
+ njs_evp_md_ctx_free(copy->ctx);
+ js_free(cx, copy);
+ JS_ThrowInternalError(cx, "EVP_MD_CTX_copy_ex() failed");
+ return JS_EXCEPTION;
+ }
obj = JS_NewObjectClass(cx, QJS_CORE_CLASS_CRYPTO_HASH);
if (JS_IsException(obj)) {
+ njs_evp_md_ctx_free(copy->ctx);
js_free(cx, copy);
return obj;
}
qjs_crypto_create_hmac(JSContext *cx, JSValueConst this_val, int argc,
JSValueConst *argv)
{
- int i;
- JS_BOOL key_is_string;
- JSValue obj;
- njs_str_t key;
- qjs_hmac_t *hmac;
- qjs_bytes_t bytes;
- qjs_hash_alg_t *alg;
- u_char digest[32], key_buf[64];
-
- alg = qjs_crypto_algorithm(cx, argv[0]);
- if (alg == NULL) {
+ JS_BOOL key_is_string;
+ JSValue obj;
+ njs_str_t key;
+ qjs_hmac_t *hmac;
+ qjs_bytes_t bytes;
+ const EVP_MD *md;
+
+ md = qjs_crypto_algorithm(cx, argv[0]);
+ if (md == NULL) {
return JS_EXCEPTION;
}
return JS_ThrowOutOfMemory(cx);
}
- hmac->alg = alg;
+ hmac->ctx = njs_hmac_ctx_new();
+ if (hmac->ctx == NULL) {
+ js_free(cx, hmac);
+ if (key_is_string) {
+ JS_FreeCString(cx, (const char *) key.start);
+ }
- if (key.length > sizeof(key_buf)) {
- alg->init(&hmac->ctx);
- alg->update(&hmac->ctx, key.start, key.length);
- alg->final(digest, &hmac->ctx);
+ return JS_ThrowOutOfMemory(cx);
+ }
- memcpy(key_buf, digest, alg->size);
- memset(key_buf + alg->size, 0, sizeof(key_buf) - alg->size);
+ if (HMAC_Init_ex(hmac->ctx, key.start, (int) key.length, md, NULL) <= 0) {
+ njs_hmac_ctx_free(hmac->ctx);
+ js_free(cx, hmac);
+ if (key_is_string) {
+ JS_FreeCString(cx, (const char *) key.start);
+ }
- } else {
- memcpy(key_buf, key.start, key.length);
- memset(key_buf + key.length, 0, sizeof(key_buf) - key.length);
+ JS_ThrowInternalError(cx, "HMAC_Init_ex() failed");
+ return JS_EXCEPTION;
}
if (key_is_string) {
JS_FreeCString(cx, (const char *) key.start);
}
- for (i = 0; i < 64; i++) {
- hmac->opad[i] = key_buf[i] ^ 0x5c;
- }
-
- for (i = 0; i < 64; i++) {
- key_buf[i] ^= 0x36;
- }
-
- alg->init(&hmac->ctx);
- alg->update(&hmac->ctx, key_buf, 64);
-
obj = JS_NewObjectClass(cx, QJS_CORE_CLASS_CRYPTO_HMAC);
if (JS_IsException(obj)) {
+ njs_hmac_ctx_free(hmac->ctx);
js_free(cx, hmac);
return obj;
}
dgst = JS_GetOpaque(val, QJS_CORE_CLASS_CRYPTO_HASH);
if (dgst != NULL) {
+ if (dgst->ctx != NULL) {
+ njs_evp_md_ctx_free(dgst->ctx);
+ }
+
js_free_rt(rt, dgst);
}
}
hmac = JS_GetOpaque(val, QJS_CORE_CLASS_CRYPTO_HMAC);
if (hmac != NULL) {
+ if (hmac->ctx != NULL) {
+ njs_hmac_ctx_free(hmac->ctx);
+ }
+
js_free_rt(rt, hmac);
}
}
-static qjs_hash_alg_t *
+static const EVP_MD *
qjs_crypto_algorithm(JSContext *cx, JSValueConst val)
{
- njs_str_t name;
- qjs_hash_alg_t *a, *alg;
+ size_t len;
+ const char *name;
+ const EVP_MD *md;
- name.start = (u_char *) JS_ToCStringLen(cx, &name.length, val);
- if (name.start == NULL) {
+ name = JS_ToCStringLen(cx, &len, val);
+ if (name == NULL) {
JS_ThrowTypeError(cx, "algorithm must be a string");
return NULL;
}
- alg = NULL;
-
- for (a = &qjs_hash_algorithms[0]; a->name.start != NULL; a++) {
- if (njs_strstr_eq(&name, &a->name)) {
- alg = a;
- break;
- }
+ if (njs_strlen(name) != len) {
+ JS_FreeCString(cx, name);
+ JS_ThrowTypeError(cx, "not supported algorithm");
+ return NULL;
}
- JS_FreeCString(cx, (const char *) name.start);
+ md = EVP_get_digestbyname(name);
- if (alg == NULL) {
+ JS_FreeCString(cx, name);
+
+ if (md == NULL) {
JS_ThrowTypeError(cx, "not supported algorithm");
+ return NULL;
}
- return alg;
+ return md;
}
if [ $NJS_OPENSSL != NO ]; then
NJS_OPENSSL_LIB=OPENSSL
have=NJS_HAVE_OPENSSL . auto/have
+ NJS_SRCS="$NJS_SRCS $ngx_addon_dir/../external/njs_crypto_module.c"
NJS_SRCS="$NJS_SRCS $ngx_addon_dir/../external/njs_webcrypto_module.c"
if [ "$NJS_HAVE_QUICKJS" = "YES" ]; then
+ NJS_SRCS="$NJS_SRCS $ngx_addon_dir/../external/qjs_crypto_module.c"
NJS_SRCS="$NJS_SRCS $ngx_addon_dir/../external/qjs_webcrypto_module.c"
fi
- echo " enabled webcrypto module"
+ echo " enabled crypto and webcrypto modules"
fi
if [ $NJS_LIBXSLT != NO ]; then
" at require (native)\n"
" at main (:1)\n") },
+ { njs_str("import cr from 'unknown'"),
+ njs_str("Error: Cannot load module \"unknown\"") },
+
+#if (NJS_HAVE_OPENSSL)
+
{ njs_str("var cr = require('crypto'); cr.createHash"),
njs_str("[object Function]") },
{ njs_str("var cr = require('crypto'); cr.createHash('md5')"),
njs_str("[object Hash]") },
- { njs_str("import cr from 'unknown'"),
- njs_str("Error: Cannot load module \"unknown\"") },
-
{ njs_str("import cr from 'crypto'; cr.createHash"),
njs_str("[object Function]") },
{ njs_str("import cr from 'crypto'; cr.createHash('md5')"),
njs_str("[object Hash]") },
+#endif
{ njs_str("var fs = require('fs'); fs.a = 1; fs.a"),
njs_str("1") },
" at require (native)\n"
" at main (:1)\n") },
+#if (NJS_HAVE_OPENSSL)
{ njs_str("require('crypto').createHash('sha')"),
njs_str("TypeError: not supported algorithm: \"sha\"\n"
" at createHash (native)\n"
njs_str("TypeError: data is not a string or Buffer-like object\n"
" at update (native)\n"
" at main (:1)\n") },
+#endif
{ njs_str("function f(o) {function f_in(o) {return o.a.a};"
" return f_in(o)};"
import cr from 'crypto';
+function has_algorithm(alg) {
+ try {
+ cr.createHash(alg).digest();
+ return true;
+ } catch (e) {
+ return false;
+ }
+}
+
let createHash_tsuite = {
name: "createHash tests",
skip: () => !cr.createHash,
{ hash: 'sha256', data: [Buffer.from('XABX').subarray(1,3)], digest: 'base64url',
expected: "OBZPvRdgPXP2lri01yZk1zW7anyIV3aH_SrjP9aWQVM" },
+ { hash: 'sha384', data: [], digest: 'hex',
+ expected: "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b" },
+ { hash: 'sha384', data: ['AB'], digest: 'hex',
+ expected: "4f9179c7b48de00c642b3782c3f9435bf21bde99cbf9ca13b6c3f1e58fff9064ad47464da97e6277c7f438d8f5a91d6b" },
+ { hash: 'sha384', data: ['A', 'B'], digest: 'hex',
+ expected: "4f9179c7b48de00c642b3782c3f9435bf21bde99cbf9ca13b6c3f1e58fff9064ad47464da97e6277c7f438d8f5a91d6b" },
+
+ { hash: 'sha512', data: [], digest: 'hex',
+ expected: "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e" },
+ { hash: 'sha512', data: ['AB'], digest: 'hex',
+ expected: "71edc062331872ff3c13c77d98f4af0e8e27bb360d03690558beab6711f9733e5dc7f114b7af58cfbcd6360575873c09a667a9af749dc912e4ca276a7dfee5d3" },
+ { hash: 'sha512', data: ['A', 'B'], digest: 'hex',
+ expected: "71edc062331872ff3c13c77d98f4af0e8e27bb360d03690558beab6711f9733e5dc7f114b7af58cfbcd6360575873c09a667a9af749dc912e4ca276a7dfee5d3" },
+
+ { hash: 'sha3-256', skip: () => !has_algorithm('sha3-256'),
+ data: [], digest: 'hex',
+ expected: "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a" },
+ { hash: 'sha3-256', skip: () => !has_algorithm('sha3-256'),
+ data: ['AB'], digest: 'hex',
+ expected: "21f29d555c7c5f9e5859a7984c0b2f8ccad9d5245fbe6c4703fd75c0922d7735" },
+ { hash: 'sha3-256', skip: () => !has_algorithm('sha3-256'),
+ data: ['A', 'B'], digest: 'hex',
+ expected: "21f29d555c7c5f9e5859a7984c0b2f8ccad9d5245fbe6c4703fd75c0922d7735" },
+
+ { hash: 'sha3-512', skip: () => !has_algorithm('sha3-512'),
+ data: [], digest: 'hex',
+ expected: "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26" },
+ { hash: 'sha3-512', skip: () => !has_algorithm('sha3-512'),
+ data: ['AB'], digest: 'hex',
+ expected: "fcc802621fee9efe4d8ee032d886f75431edb29d480e945d8f0efb1c0ad419bf9b652fca1fa1f5af0f5b4a74f76a6e86b00dbfbec7dcf00e3f4ef34840e9b720" },
+
{ hash: 'sha1',
hash_value(hash) {
var Hash = cr.createHash(hash).constructor;
{ hash: 'sha256', key: 'A'.repeat(100), data: ['AB'], digest: 'hex',
expected: "5647b6c429701ff512f0f18232b4507065d2376ca8899a816a0a6e721bf8ddcc" },
+ { hash: 'sha384', key: '', data: [], digest: 'hex',
+ expected: "6c1f2ee938fad2e24bd91298474382ca218c75db3d83e114b3d4367776d14d3551289e75e8209cd4b792302840234adc" },
+ { hash: 'sha384', key: '', data: ['AB'], digest: 'hex',
+ expected: "0145ec85556f28b82b49d7bd8c3373312d95c308b758e3bd3cd972f8ab9d0ea9245f60ef5b994ec936eb42c6fc7ca033" },
+ { hash: 'sha384', key: Buffer.from('secret'), data: ['AB'], digest: 'hex',
+ expected: "afb6653433bc3b3e570fa9c7f0fa1f40d070af21085d7292ce8c93c4a280c2c91b1da980c39a3738361458c75a8c6f64" },
+
+ { hash: 'sha512', key: '', data: [], digest: 'hex',
+ expected: "b936cee86c9f87aa5d3c6f2e84cb5a4239a5fe50480a6ec66b70ab5b1f4ac6730c6c515421b327ec1d69402e53dfb49ad7381eb067b338fd7b0cb22247225d47" },
+ { hash: 'sha512', key: '', data: ['AB'], digest: 'hex',
+ expected: "8bf9155a8dbd563d879ecb5ad27e7b9e8e30ab98c138802594bedd9d839ddecb85443fdc64e18274311975b4ec1c5dd5dc41a6e7530cf34ea3d6545cf5844501" },
+ { hash: 'sha512', key: Buffer.from('secret'), data: ['AB'], digest: 'hex',
+ expected: "1169372f39b4ea921bed3cff6d029c0be7116bf2966098b9923d0730e9bd569e2f52e65f63c3adebe988b0be174fd42578b1536f1f1b8b46a1382da55e27de9d" },
+
+ { hash: 'sha512', key: 'A'.repeat(200), data: ['AB'], digest: 'hex',
+ expected: "d64ea04999cba0f2f167f471569129f9b3105a2e099fb883be3cdee452b38cf7c34d1705b83caaaf784dd4e63703a328d9a5167b03dd059d516b386ff86d5a40" },
+
{ hash: 'sha1',
hmac_value(hash, key) {
var Hmac = cr.createHmac(hash, key).constructor;