From: Dmitry Volyntsev Date: Wed, 3 May 2023 03:50:57 +0000 (-0700) Subject: WebCrypto: module is rewritten using public API. X-Git-Url: http://www.kaiwu.me/postgresql/commit/?a=commitdiff_plain;h=4a061308fd1d95002d4c619e85118dfa95bcc03d;p=njs.git WebCrypto: module is rewritten using public API. --- diff --git a/external/njs_webcrypto_module.c b/external/njs_webcrypto_module.c index 2c738498..9e250bd2 100644 --- a/external/njs_webcrypto_module.c +++ b/external/njs_webcrypto_module.c @@ -5,7 +5,9 @@ */ -#include +#include +#include +#include #include "njs_openssl.h" typedef enum { @@ -126,7 +128,8 @@ static njs_webcrypto_key_format_t njs_key_format(njs_vm_t *vm, static njs_str_t *njs_format_string(njs_webcrypto_key_format_t fmt); static njs_int_t njs_key_usage(njs_vm_t *vm, njs_value_t *value, unsigned *mask); -static njs_int_t njs_key_ops(njs_vm_t *vm, njs_value_t *retval, unsigned mask); +static njs_int_t njs_key_ops(njs_vm_t *vm, njs_opaque_value_t *retval, + unsigned mask); static njs_webcrypto_algorithm_t *njs_key_algorithm(njs_vm_t *vm, njs_value_t *value); static njs_str_t *njs_algorithm_string(njs_webcrypto_algorithm_t *algorithm); @@ -136,7 +139,7 @@ static const EVP_MD *njs_algorithm_hash_digest(njs_webcrypto_hash_t hash); static njs_int_t njs_algorithm_curve(njs_vm_t *vm, njs_value_t *value, int *curve); -static njs_int_t njs_webcrypto_result(njs_vm_t *vm, njs_value_t *result, +static njs_int_t njs_webcrypto_result(njs_vm_t *vm, njs_opaque_value_t *result, njs_int_t rc, njs_value_t *retval); static njs_int_t njs_webcrypto_array_buffer(njs_vm_t *vm, njs_value_t *retval, u_char *start, size_t length); @@ -593,23 +596,23 @@ njs_module_t njs_webcrypto_module = { }; -static const njs_value_t string_alg = njs_string("alg"); -static const njs_value_t string_d = njs_string("d"); -static const njs_value_t string_dp = njs_string("dp"); -static const njs_value_t string_dq = njs_string("dq"); -static const njs_value_t string_e = njs_string("e"); -static const njs_value_t string_k = njs_string("k"); -static const njs_value_t string_n = njs_string("n"); -static const njs_value_t string_p = njs_string("p"); -static const njs_value_t string_q = njs_string("q"); -static const njs_value_t string_qi = njs_string("qi"); -static const njs_value_t string_x = njs_string("x"); -static const njs_value_t string_y = njs_string("y"); -static const njs_value_t string_ext = njs_string("ext"); -static const njs_value_t string_crv = njs_string("crv"); -static const njs_value_t string_kty = njs_string("kty"); -static const njs_value_t key_ops = njs_string("key_ops"); -static const njs_value_t string_length = njs_string("length"); +static const njs_str_t string_alg = njs_str("alg"); +static const njs_str_t string_d = njs_str("d"); +static const njs_str_t string_dp = njs_str("dp"); +static const njs_str_t string_dq = njs_str("dq"); +static const njs_str_t string_e = njs_str("e"); +static const njs_str_t string_k = njs_str("k"); +static const njs_str_t string_n = njs_str("n"); +static const njs_str_t string_p = njs_str("p"); +static const njs_str_t string_q = njs_str("q"); +static const njs_str_t string_qi = njs_str("qi"); +static const njs_str_t string_x = njs_str("x"); +static const njs_str_t string_y = njs_str("y"); +static const njs_str_t string_ext = njs_str("ext"); +static const njs_str_t string_crv = njs_str("crv"); +static const njs_str_t string_kty = njs_str("kty"); +static const njs_str_t key_ops = njs_str("key_ops"); +static const njs_str_t string_length = njs_str("length"); static njs_int_t njs_webcrypto_crypto_key_proto_id; @@ -622,7 +625,8 @@ njs_ext_cipher(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, unsigned mask; njs_int_t ret; njs_str_t data; - njs_value_t *options, value; + njs_value_t *options; + njs_opaque_value_t result; njs_webcrypto_key_t *key; njs_webcrypto_algorithm_t *alg; @@ -635,22 +639,22 @@ njs_ext_cipher(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, key = njs_vm_external(vm, njs_webcrypto_crypto_key_proto_id, njs_arg(args, nargs, 2)); if (njs_slow_path(key == NULL)) { - njs_type_error(vm, "\"key\" is not a CryptoKey object"); + njs_vm_error(vm, "\"key\" is not a CryptoKey object"); goto fail; } mask = encrypt ? NJS_KEY_USAGE_ENCRYPT : NJS_KEY_USAGE_DECRYPT; if (njs_slow_path(!(key->usage & mask))) { - njs_type_error(vm, "provide key does not support %s operation", - encrypt ? "encrypt" : "decrypt"); + njs_vm_error(vm, "provide key does not support %s operation", + encrypt ? "encrypt" : "decrypt"); goto fail; } if (njs_slow_path(key->alg != alg)) { - njs_type_error(vm, "cannot %s using \"%V\" with \"%V\" key", - encrypt ? "encrypt" : "decrypt", - njs_algorithm_string(key->alg), - njs_algorithm_string(alg)); + njs_vm_error(vm, "cannot %s using \"%V\" with \"%V\" key", + encrypt ? "encrypt" : "decrypt", + njs_algorithm_string(key->alg), + njs_algorithm_string(alg)); goto fail; } @@ -661,23 +665,26 @@ njs_ext_cipher(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, switch (alg->type) { case NJS_ALGORITHM_RSA_OAEP: - ret = njs_cipher_pkey(vm, &data, key, encrypt, &value); + ret = njs_cipher_pkey(vm, &data, key, encrypt, njs_value_arg(&result)); break; case NJS_ALGORITHM_AES_GCM: - ret = njs_cipher_aes_gcm(vm, &data, key, options, encrypt, &value); + ret = njs_cipher_aes_gcm(vm, &data, key, options, encrypt, + njs_value_arg(&result)); break; case NJS_ALGORITHM_AES_CTR: - ret = njs_cipher_aes_ctr(vm, &data, key, options, encrypt, &value); + ret = njs_cipher_aes_ctr(vm, &data, key, options, encrypt, + njs_value_arg(&result)); break; case NJS_ALGORITHM_AES_CBC: default: - ret = njs_cipher_aes_cbc(vm, &data, key, options, encrypt, &value); + ret = njs_cipher_aes_cbc(vm, &data, key, options, encrypt, + njs_value_arg(&result)); } - return njs_webcrypto_result(vm, &value, ret, retval); + return njs_webcrypto_result(vm, &result, ret, retval); fail: @@ -736,7 +743,7 @@ njs_cipher_pkey(njs_vm_t *vm, njs_str_t *data, njs_webcrypto_key_t *key, dst = njs_mp_alloc(njs_vm_memory_pool(vm), outlen); if (njs_slow_path(dst == NULL)) { - njs_memory_error(vm); + njs_vm_memory_error(vm); ret = NJS_ERROR; goto fail; } @@ -763,18 +770,19 @@ static njs_int_t njs_cipher_aes_gcm(njs_vm_t *vm, njs_str_t *data, njs_webcrypto_key_t *key, njs_value_t *options, njs_bool_t encrypt, njs_value_t *retval) { - int len, outlen, dstlen; - u_char *dst, *p; - int64_t taglen; - njs_str_t iv, aad; - njs_int_t ret; - njs_value_t value; - EVP_CIPHER_CTX *ctx; - const EVP_CIPHER *cipher; - - static const njs_value_t string_iv = njs_string("iv"); - static const njs_value_t string_ad = njs_string("additionalData"); - static const njs_value_t string_tl = njs_string("tagLength"); + int len, outlen, dstlen; + u_char *dst, *p; + int64_t taglen; + njs_str_t iv, aad; + njs_int_t ret; + njs_value_t *value; + EVP_CIPHER_CTX *ctx; + const EVP_CIPHER *cipher; + njs_opaque_value_t lvalue; + + static const njs_str_t string_iv = njs_str("iv"); + static const njs_str_t string_ad = njs_str("additionalData"); + static const njs_str_t string_tl = njs_str("tagLength"); switch (key->raw.length) { case 16: @@ -790,33 +798,26 @@ njs_cipher_aes_gcm(njs_vm_t *vm, njs_str_t *data, njs_webcrypto_key_t *key, break; default: - njs_type_error(vm, "AES-GCM Invalid key length"); + njs_vm_error(vm, "AES-GCM Invalid key length"); return NJS_ERROR; } - ret = njs_value_property(vm, options, njs_value_arg(&string_iv), &value); - if (njs_slow_path(ret != NJS_OK)) { - if (ret == NJS_DECLINED) { - njs_type_error(vm, "AES-GCM algorithm.iv is not provided"); - } - + value = njs_vm_object_prop(vm, options, &string_iv, &lvalue); + if (value == NULL) { + njs_vm_error(vm, "AES-GCM algorithm.iv is not provided"); return NJS_ERROR; } - ret = njs_vm_value_to_bytes(vm, &iv, &value); + ret = njs_vm_value_to_bytes(vm, &iv, njs_value_arg(&lvalue)); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } taglen = 128; - ret = njs_value_property(vm, options, njs_value_arg(&string_tl), &value); - if (njs_slow_path(ret == NJS_ERROR)) { - return NJS_ERROR; - } - - if (njs_is_defined(&value)) { - ret = njs_value_to_integer(vm, &value, &taglen); + value = njs_vm_object_prop(vm, options, &string_tl, &lvalue); + if (value != NULL && !njs_value_is_undefined(value)) { + ret = njs_value_to_integer(vm, value, &taglen); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -830,14 +831,14 @@ njs_cipher_aes_gcm(njs_vm_t *vm, njs_str_t *data, njs_webcrypto_key_t *key, && taglen != 120 && taglen != 128)) { - njs_type_error(vm, "AES-GCM Invalid tagLength"); + njs_vm_error(vm, "AES-GCM Invalid tagLength"); return NJS_ERROR; } taglen /= 8; if (njs_slow_path(!encrypt && (data->length < (size_t) taglen))) { - njs_type_error(vm, "AES-GCM data is too short"); + njs_vm_error(vm, "AES-GCM data is too short"); return NJS_ERROR; } @@ -881,15 +882,11 @@ njs_cipher_aes_gcm(njs_vm_t *vm, njs_str_t *data, njs_webcrypto_key_t *key, } } - ret = njs_value_property(vm, options, njs_value_arg(&string_ad), &value); - if (njs_slow_path(ret == NJS_ERROR)) { - return NJS_ERROR; - } - aad.length = 0; - if (njs_is_defined(&value)) { - ret = njs_vm_value_to_bytes(vm, &aad, &value); + value = njs_vm_object_prop(vm, options, &string_ad, &lvalue); + if (value != NULL && !njs_value_is_undefined(value)) { + ret = njs_vm_value_to_bytes(vm, &aad, value); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -908,7 +905,7 @@ njs_cipher_aes_gcm(njs_vm_t *vm, njs_str_t *data, njs_webcrypto_key_t *key, dstlen = data->length + EVP_CIPHER_CTX_block_size(ctx) + taglen; dst = njs_mp_alloc(njs_vm_memory_pool(vm), dstlen); if (njs_slow_path(dst == NULL)) { - njs_memory_error(vm); + njs_vm_memory_error(vm); return NJS_ERROR; } @@ -1064,18 +1061,19 @@ static njs_int_t njs_cipher_aes_ctr(njs_vm_t *vm, njs_str_t *data, njs_webcrypto_key_t *key, njs_value_t *options, njs_bool_t encrypt, njs_value_t *retval) { - int len, len2; - u_char *dst; - int64_t length; - BIGNUM *total, *blocks, *left, *ctr; - njs_int_t ret; - njs_str_t iv; - njs_uint_t size1; - njs_value_t value; - const EVP_CIPHER *cipher; - u_char iv2[16]; - - static const njs_value_t string_counter = njs_string("counter"); + int len, len2; + u_char *dst; + int64_t length; + BIGNUM *total, *blocks, *left, *ctr; + njs_int_t ret; + njs_str_t iv; + njs_uint_t size1; + njs_value_t *value; + const EVP_CIPHER *cipher; + njs_opaque_value_t lvalue; + u_char iv2[16]; + + static const njs_str_t string_counter = njs_str("counter"); switch (key->raw.length) { case 16: @@ -1091,48 +1089,39 @@ njs_cipher_aes_ctr(njs_vm_t *vm, njs_str_t *data, njs_webcrypto_key_t *key, break; default: - njs_type_error(vm, "AES-CTR Invalid key length"); + njs_vm_error(vm, "AES-CTR Invalid key length"); return NJS_ERROR; } - ret = njs_value_property(vm, options, njs_value_arg(&string_counter), - &value); - if (njs_slow_path(ret != NJS_OK)) { - if (ret == NJS_DECLINED) { - njs_type_error(vm, "AES-CTR algorithm.counter is not provided"); - } - + value = njs_vm_object_prop(vm, options, &string_counter, &lvalue); + if (value == NULL) { + njs_vm_error(vm, "AES-CTR algorithm.counter is not provided"); return NJS_ERROR; } - ret = njs_vm_value_to_bytes(vm, &iv, &value); + ret = njs_vm_value_to_bytes(vm, &iv, value); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } if (njs_slow_path(iv.length != 16)) { - njs_type_error(vm, "AES-CTR algorithm.counter must be 16 bytes long"); + njs_vm_error(vm, "AES-CTR algorithm.counter must be 16 bytes long"); return NJS_ERROR; } - ret = njs_value_property(vm, options, njs_value_arg(&string_length), - &value); - if (njs_slow_path(ret != NJS_OK)) { - if (ret == NJS_DECLINED) { - njs_type_error(vm, "AES-CTR algorithm.length is not provided"); - } - + value = njs_vm_object_prop(vm, options, &string_length, &lvalue); + if (value == NULL) { + njs_vm_error(vm, "AES-CTR algorithm.length is not provided"); return NJS_ERROR; } - ret = njs_value_to_integer(vm, &value, &length); + ret = njs_value_to_integer(vm, value, &length); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } if (njs_slow_path(length == 0 || length > 128)) { - njs_type_error(vm, "AES-CTR algorithm.length " - "must be between 1 and 128"); + njs_vm_error(vm, "AES-CTR algorithm.length must be between 1 and 128"); return NJS_ERROR; } @@ -1175,7 +1164,7 @@ njs_cipher_aes_ctr(njs_vm_t *vm, njs_str_t *data, njs_webcrypto_key_t *key, ret = BN_cmp(blocks, total); if (njs_slow_path(ret > 0)) { - njs_type_error(vm, "AES-CTR repeated counter"); + njs_vm_error(vm, "AES-CTR repeated counter"); ret = NJS_ERROR; goto fail; } @@ -1196,7 +1185,7 @@ njs_cipher_aes_ctr(njs_vm_t *vm, njs_str_t *data, njs_webcrypto_key_t *key, dst = njs_mp_alloc(njs_vm_memory_pool(vm), data->length + EVP_MAX_BLOCK_LENGTH); if (njs_slow_path(dst == NULL)) { - njs_memory_error(vm); + njs_vm_memory_error(vm); return NJS_ERROR; } @@ -1271,16 +1260,17 @@ static njs_int_t njs_cipher_aes_cbc(njs_vm_t *vm, njs_str_t *data, njs_webcrypto_key_t *key, njs_value_t *options, njs_bool_t encrypt, njs_value_t *retval) { - int olen_max, olen, olen2; - u_char *dst; - unsigned remainder; - njs_str_t iv; - njs_int_t ret; - njs_value_t value; - EVP_CIPHER_CTX *ctx; - const EVP_CIPHER *cipher; - - static const njs_value_t string_iv = njs_string("iv"); + int olen_max, olen, olen2; + u_char *dst; + unsigned remainder; + njs_str_t iv; + njs_int_t ret; + njs_value_t *value; + EVP_CIPHER_CTX *ctx; + const EVP_CIPHER *cipher; + njs_opaque_value_t lvalue; + + static const njs_str_t string_iv = njs_str("iv"); switch (key->raw.length) { case 16: @@ -1296,26 +1286,23 @@ njs_cipher_aes_cbc(njs_vm_t *vm, njs_str_t *data, njs_webcrypto_key_t *key, break; default: - njs_type_error(vm, "AES-CBC Invalid key length"); + njs_vm_error(vm, "AES-CBC Invalid key length"); return NJS_ERROR; } - ret = njs_value_property(vm, options, njs_value_arg(&string_iv), &value); - if (njs_slow_path(ret != NJS_OK)) { - if (ret == NJS_DECLINED) { - njs_type_error(vm, "AES-CBC algorithm.iv is not provided"); - } - + value = njs_vm_object_prop(vm, options, &string_iv, &lvalue); + if (value == NULL) { + njs_vm_error(vm, "AES-CBC algorithm.iv is not provided"); return NJS_ERROR; } - ret = njs_vm_value_to_bytes(vm, &iv, &value); + ret = njs_vm_value_to_bytes(vm, &iv, value); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } if (njs_slow_path(iv.length != 16)) { - njs_type_error(vm, "AES-CBC algorithm.iv must be 16 bytes long"); + njs_vm_error(vm, "AES-CBC algorithm.iv must be 16 bytes long"); return NJS_ERROR; } @@ -1343,7 +1330,7 @@ njs_cipher_aes_cbc(njs_vm_t *vm, njs_str_t *data, njs_webcrypto_key_t *key, dst = njs_mp_alloc(njs_vm_memory_pool(vm), olen_max); if (njs_slow_path(dst == NULL)) { - njs_memory_error(vm); + njs_vm_memory_error(vm); ret = NJS_ERROR; goto fail; } @@ -1386,16 +1373,17 @@ njs_ext_derive(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, unsigned usage, mask; njs_int_t ret; njs_str_t salt, info; - njs_value_t value, *aobject, *dobject; + njs_value_t *value, *aobject, *dobject; const EVP_MD *md; EVP_PKEY_CTX *pctx; njs_webcrypto_key_t *key, *dkey; + njs_opaque_value_t lvalue; njs_webcrypto_hash_t hash; njs_webcrypto_algorithm_t *alg, *dalg; - static const njs_value_t string_info = njs_string("info"); - static const njs_value_t string_salt = njs_string("salt"); - static const njs_value_t string_iterations = njs_string("iterations"); + static const njs_str_t string_info = njs_str("info"); + static const njs_str_t string_salt = njs_str("salt"); + static const njs_str_t string_iterations = njs_str("iterations"); aobject = njs_arg(args, nargs, 1); alg = njs_key_algorithm(vm, aobject); @@ -1406,22 +1394,22 @@ njs_ext_derive(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, key = njs_vm_external(vm, njs_webcrypto_crypto_key_proto_id, njs_arg(args, nargs, 2)); if (njs_slow_path(key == NULL)) { - njs_type_error(vm, "\"baseKey\" is not a CryptoKey object"); + njs_vm_error(vm, "\"baseKey\" is not a CryptoKey object"); goto fail; } mask = derive_key ? NJS_KEY_USAGE_DERIVE_KEY : NJS_KEY_USAGE_DERIVE_BITS; if (njs_slow_path(!(key->usage & mask))) { - njs_type_error(vm, "provide key does not support \"%s\" operation", - derive_key ? "deriveKey" : "deriveBits"); + njs_vm_error(vm, "provide key does not support \"%s\" operation", + derive_key ? "deriveKey" : "deriveBits"); goto fail; } if (njs_slow_path(key->alg != alg)) { - njs_type_error(vm, "cannot derive %s using \"%V\" with \"%V\" key", - derive_key ? "key" : "bits", - njs_algorithm_string(key->alg), - njs_algorithm_string(alg)); + njs_vm_error(vm, "cannot derive %s using \"%V\" with \"%V\" key", + derive_key ? "key" : "bits", + njs_algorithm_string(key->alg), + njs_algorithm_string(alg)); goto fail; } @@ -1433,22 +1421,18 @@ njs_ext_derive(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, goto fail; } - ret = njs_value_property(vm, dobject, njs_value_arg(&string_length), - &value); - if (njs_slow_path(ret != NJS_OK)) { - if (ret == NJS_DECLINED) { - njs_type_error(vm, "derivedKeyAlgorithm.length " - "is not provided"); - goto fail; - } + value = njs_vm_object_prop(vm, dobject, &string_length, &lvalue); + if (value == NULL) { + njs_vm_error(vm, "derivedKeyAlgorithm.length is not provided"); + goto fail; } } else { dalg = NULL; - njs_value_assign(&value, dobject); + value = dobject; } - ret = njs_value_to_integer(vm, &value, &length); + ret = njs_value_to_integer(vm, value, &length); if (njs_slow_path(ret != NJS_OK)) { goto fail; } @@ -1463,16 +1447,16 @@ njs_ext_derive(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, case NJS_ALGORITHM_AES_CBC: if (length != 16 && length != 32) { - njs_type_error(vm, "deriveKey \"%V\" length must be 128 or 256", - njs_algorithm_string(dalg)); + njs_vm_error(vm, "deriveKey \"%V\" length must be 128 or 256", + njs_algorithm_string(dalg)); goto fail; } break; default: - njs_internal_error(vm, "not implemented deriveKey: \"%V\"", - njs_algorithm_string(dalg)); + njs_vm_error(vm, "not implemented deriveKey: \"%V\"", + njs_algorithm_string(dalg)); goto fail; } @@ -1482,15 +1466,15 @@ njs_ext_derive(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } if (njs_slow_path(usage & ~dalg->usage)) { - njs_type_error(vm, "unsupported key usage for \"%V\" key", - njs_algorithm_string(alg)); + njs_vm_error(vm, "unsupported key usage for \"%V\" key", + njs_algorithm_string(alg)); goto fail; } dkey = njs_mp_zalloc(njs_vm_memory_pool(vm), sizeof(njs_webcrypto_key_t)); if (njs_slow_path(dkey == NULL)) { - njs_memory_error(vm); + njs_vm_memory_error(vm); goto fail; } @@ -1500,7 +1484,7 @@ njs_ext_derive(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, k = njs_mp_zalloc(njs_vm_memory_pool(vm), length); if (njs_slow_path(k == NULL)) { - njs_memory_error(vm); + njs_vm_memory_error(vm); goto fail; } @@ -1511,39 +1495,30 @@ njs_ext_derive(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, goto fail; } - ret = njs_value_property(vm, aobject, njs_value_arg(&string_salt), - &value); - if (njs_slow_path(ret != NJS_OK)) { - if (ret == NJS_DECLINED) { - njs_type_error(vm, "PBKDF2 algorithm.salt is not provided"); - } - + value = njs_vm_object_prop(vm, aobject, &string_salt, &lvalue); + if (value == NULL) { + njs_vm_error(vm, "PBKDF2 algorithm.salt is not provided"); goto fail; } - ret = njs_vm_value_to_bytes(vm, &salt, &value); + ret = njs_vm_value_to_bytes(vm, &salt, value); if (njs_slow_path(ret != NJS_OK)) { goto fail; } if (njs_slow_path(salt.length < 16)) { - njs_type_error(vm, "PBKDF2 algorithm.salt must be " - "at least 16 bytes long"); + njs_vm_error(vm, "PBKDF2 algorithm.salt must be " + "at least 16 bytes long"); goto fail; } - ret = njs_value_property(vm, aobject, njs_value_arg(&string_iterations), - &value); - if (njs_slow_path(ret != NJS_OK)) { - if (ret == NJS_DECLINED) { - njs_type_error(vm, "PBKDF2 algorithm.iterations " - "is not provided"); - } - + value = njs_vm_object_prop(vm, aobject, &string_iterations, &lvalue); + if (value == NULL) { + njs_vm_error(vm, "PBKDF2 algorithm.iterations is not provided"); goto fail; } - ret = njs_value_to_integer(vm, &value, &iterations); + ret = njs_value_to_integer(vm, value, &iterations); if (njs_slow_path(ret != NJS_OK)) { goto fail; } @@ -1566,32 +1541,24 @@ njs_ext_derive(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, goto fail; } - ret = njs_value_property(vm, aobject, njs_value_arg(&string_salt), - &value); - if (njs_slow_path(ret != NJS_OK)) { - if (ret == NJS_DECLINED) { - njs_type_error(vm, "HKDF algorithm.salt is not provided"); - } - + value = njs_vm_object_prop(vm, aobject, &string_salt, &lvalue); + if (value == NULL) { + njs_vm_error(vm, "HKDF algorithm.salt is not provided"); goto fail; } - ret = njs_vm_value_to_bytes(vm, &salt, &value); + ret = njs_vm_value_to_bytes(vm, &salt, value); if (njs_slow_path(ret != NJS_OK)) { goto fail; } - ret = njs_value_property(vm, aobject, njs_value_arg(&string_info), - &value); - if (njs_slow_path(ret != NJS_OK)) { - if (ret == NJS_DECLINED) { - njs_type_error(vm, "HKDF algorithm.info is not provided"); - } - + value = njs_vm_object_prop(vm, aobject, &string_info, &lvalue); + if (value == NULL) { + njs_vm_error(vm, "HKDF algorithm.info is not provided"); goto fail; } - ret = njs_vm_value_to_bytes(vm, &info, &value); + ret = njs_vm_value_to_bytes(vm, &info, value); if (njs_slow_path(ret != NJS_OK)) { goto fail; } @@ -1659,8 +1626,8 @@ free: case NJS_ALGORITHM_ECDH: default: - njs_internal_error(vm, "not implemented deriveKey " - "algorithm: \"%V\"", njs_algorithm_string(alg)); + njs_vm_error(vm, "not implemented deriveKey " + "algorithm: \"%V\"", njs_algorithm_string(alg)); goto fail; } @@ -1675,18 +1642,19 @@ free: dkey->raw.start = k; dkey->raw.length = length; - ret = njs_vm_external_create(vm, &value, + ret = njs_vm_external_create(vm, njs_value_arg(&lvalue), njs_webcrypto_crypto_key_proto_id, dkey, 0); } else { - ret = njs_vm_value_array_buffer_set(vm, &value, k, length); + ret = njs_vm_value_array_buffer_set(vm, njs_value_arg(&lvalue), k, + length); } if (njs_slow_path(ret != NJS_OK)) { goto fail; } - return njs_webcrypto_result(vm, &value, NJS_OK, retval); + return njs_webcrypto_result(vm, &lvalue, NJS_OK, retval); fail: @@ -1702,8 +1670,8 @@ njs_ext_digest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, u_char *dst; njs_str_t data; njs_int_t ret; - njs_value_t value; const EVP_MD *md; + njs_opaque_value_t result; njs_webcrypto_hash_t hash; ret = njs_algorithm_hash(vm, njs_arg(args, nargs, 1), &hash); @@ -1721,7 +1689,7 @@ njs_ext_digest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, dst = njs_mp_zalloc(njs_vm_memory_pool(vm), olen); if (njs_slow_path(dst == NULL)) { - njs_memory_error(vm); + njs_vm_memory_error(vm); goto fail; } @@ -1731,12 +1699,12 @@ njs_ext_digest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, goto fail; } - ret = njs_vm_value_array_buffer_set(vm, &value, dst, olen); + ret = njs_vm_value_array_buffer_set(vm, njs_value_arg(&result), dst, olen); if (njs_slow_path(ret != NJS_OK)) { goto fail; } - return njs_webcrypto_result(vm, &value, NJS_OK, retval); + return njs_webcrypto_result(vm, &result, NJS_OK, retval); fail: @@ -1745,8 +1713,8 @@ fail: static njs_int_t -njs_export_base64url_bignum(njs_vm_t *vm, njs_value_t *retval, const BIGNUM *v, - size_t size) +njs_export_base64url_bignum(njs_vm_t *vm, njs_opaque_value_t *retval, + const BIGNUM *v, size_t size) { njs_str_t src; u_char buf[512]; @@ -1762,36 +1730,35 @@ njs_export_base64url_bignum(njs_vm_t *vm, njs_value_t *retval, const BIGNUM *v, src.start = buf; src.length = size; - return njs_string_base64url(vm, retval, &src); + return njs_string_base64url(vm, njs_value_arg(retval), &src); } static njs_int_t -njs_base64url_bignum_set(njs_vm_t *vm, njs_value_t *jwk, njs_value_t *key, +njs_base64url_bignum_set(njs_vm_t *vm, njs_value_t *jwk, const njs_str_t *key, const BIGNUM *v, size_t size) { - njs_int_t ret; - njs_value_t value; + njs_int_t ret; + njs_opaque_value_t value; ret = njs_export_base64url_bignum(vm, &value, v, size); if (ret != NJS_OK) { return NJS_ERROR; } - return njs_value_property_set(vm, jwk, key, &value); + return njs_vm_object_prop_set(vm, jwk, key, &value); } static njs_int_t njs_export_jwk_rsa(njs_vm_t *vm, njs_webcrypto_key_t *key, njs_value_t *retval) { - njs_int_t ret; - const RSA *rsa; - njs_str_t *nm; - njs_value_t nvalue, evalue, alg; - const BIGNUM *n_bn, *e_bn, *d_bn, *p_bn, *q_bn, *dp_bn, *dq_bn, *qi_bn; - - static const njs_value_t rsa_str = njs_string("RSA"); + njs_int_t ret; + const RSA *rsa; + njs_str_t *nm; + const BIGNUM *n_bn, *e_bn, *d_bn, *p_bn, *q_bn, *dp_bn, *dq_bn, + *qi_bn; + njs_opaque_value_t nvalue, evalue, alg, rsa_s; rsa = njs_pkey_get_rsa_key(key->pkey); @@ -1807,8 +1774,24 @@ njs_export_jwk_rsa(njs_vm_t *vm, njs_webcrypto_key_t *key, njs_value_t *retval) return NJS_ERROR; } - ret = njs_vm_object_alloc(vm, retval, &string_kty, &rsa_str, &string_n, - &nvalue, &string_e, &evalue, NULL); + ret = njs_vm_object_alloc(vm, retval, NULL); + if (ret != NJS_OK) { + return NJS_ERROR; + } + + njs_vm_value_string_set(vm, njs_value_arg(&rsa_s), (u_char *) "RSA", 3); + + ret = njs_vm_object_prop_set(vm, retval, &string_kty, &rsa_s); + if (ret != NJS_OK) { + return NJS_ERROR; + } + + ret = njs_vm_object_prop_set(vm, retval, &string_n, &nvalue); + if (ret != NJS_OK) { + return NJS_ERROR; + } + + ret = njs_vm_object_prop_set(vm, retval, &string_e, &evalue); if (ret != NJS_OK) { return NJS_ERROR; } @@ -1817,38 +1800,32 @@ njs_export_jwk_rsa(njs_vm_t *vm, njs_webcrypto_key_t *key, njs_value_t *retval) njs_rsa_get0_factors(rsa, &p_bn, &q_bn); njs_rsa_get0_ctr_params(rsa, &dp_bn, &dq_bn, &qi_bn); - ret = njs_base64url_bignum_set(vm, retval, njs_value_arg(&string_d), - d_bn, 0); + ret = njs_base64url_bignum_set(vm, retval, &string_d, d_bn, 0); if (ret != NJS_OK) { return NJS_ERROR; } - ret = njs_base64url_bignum_set(vm, retval, njs_value_arg(&string_p), - p_bn, 0); + ret = njs_base64url_bignum_set(vm, retval, &string_p, p_bn, 0); if (ret != NJS_OK) { return NJS_ERROR; } - ret = njs_base64url_bignum_set(vm, retval, njs_value_arg(&string_q), - q_bn, 0); + ret = njs_base64url_bignum_set(vm, retval, &string_q, q_bn, 0); if (ret != NJS_OK) { return NJS_ERROR; } - ret = njs_base64url_bignum_set(vm, retval, njs_value_arg(&string_dp), - dp_bn, 0); + ret = njs_base64url_bignum_set(vm, retval, &string_dp, dp_bn, 0); if (ret != NJS_OK) { return NJS_ERROR; } - ret = njs_base64url_bignum_set(vm, retval, njs_value_arg(&string_dq), - dq_bn, 0); + ret = njs_base64url_bignum_set(vm, retval, &string_dq, dq_bn, 0); if (ret != NJS_OK) { return NJS_ERROR; } - ret = njs_base64url_bignum_set(vm, retval, njs_value_arg(&string_qi), - qi_bn, 0); + ret = njs_base64url_bignum_set(vm, retval, &string_qi, qi_bn, 0); if (ret != NJS_OK) { return NJS_ERROR; } @@ -1856,9 +1833,10 @@ njs_export_jwk_rsa(njs_vm_t *vm, njs_webcrypto_key_t *key, njs_value_t *retval) nm = &njs_webcrypto_alg_name[key->alg->type][key->hash]; - (void) njs_vm_value_string_set(vm, &alg, nm->start, nm->length); + (void) njs_vm_value_string_set(vm, njs_value_arg(&alg), nm->start, + nm->length); - return njs_value_property_set(vm, retval, njs_value_arg(&string_alg), &alg); + return njs_vm_object_prop_set(vm, retval, &string_alg, &alg); } @@ -1868,15 +1846,13 @@ njs_export_jwk_ec(njs_vm_t *vm, njs_webcrypto_key_t *key, njs_value_t *retval) int nid, group_bits, group_bytes; BIGNUM *x_bn, *y_bn; njs_int_t ret; - njs_value_t xvalue, yvalue, dvalue, name; const EC_KEY *ec; const BIGNUM *d_bn; const EC_POINT *pub; const EC_GROUP *group; + njs_opaque_value_t xvalue, yvalue, dvalue, name, ec_s; njs_webcrypto_entry_t *e; - static const njs_value_t ec_str = njs_string("EC"); - x_bn = NULL; y_bn = NULL; d_bn = NULL; @@ -1924,24 +1900,44 @@ njs_export_jwk_ec(njs_vm_t *vm, njs_webcrypto_key_t *key, njs_value_t *retval) for (e = &njs_webcrypto_curve[0]; e->name.length != 0; e++) { if ((uintptr_t) nid == e->value) { - (void) njs_vm_value_string_set(vm, &name, e->name.start, - e->name.length); + (void) njs_vm_value_string_set(vm, njs_value_arg(&name), + e->name.start, e->name.length); break; } } if (e->name.length == 0) { - njs_type_error(vm, "Unsupported JWK EC curve: %s", OBJ_nid2sn(nid)); + njs_vm_error(vm, "Unsupported JWK EC curve: %s", OBJ_nid2sn(nid)); goto fail; } - ret = njs_vm_object_alloc(vm, retval, &string_kty, &ec_str, &string_x, - &xvalue, &string_y, &yvalue, &string_crv, &name, - NULL); + ret = njs_vm_object_alloc(vm, retval, NULL); if (ret != NJS_OK) { goto fail; } + njs_vm_value_string_set(vm, njs_value_arg(&ec_s), (u_char *) "EC", 2); + + ret = njs_vm_object_prop_set(vm, retval, &string_kty, &ec_s); + if (ret != NJS_OK) { + return NJS_ERROR; + } + + ret = njs_vm_object_prop_set(vm, retval, &string_x, &xvalue); + if (ret != NJS_OK) { + return NJS_ERROR; + } + + ret = njs_vm_object_prop_set(vm, retval, &string_y, &yvalue); + if (ret != NJS_OK) { + return NJS_ERROR; + } + + ret = njs_vm_object_prop_set(vm, retval, &string_crv, &name); + if (ret != NJS_OK) { + return NJS_ERROR; + } + if (key->privat) { d_bn = EC_KEY_get0_private_key(ec); @@ -1950,8 +1946,7 @@ njs_export_jwk_ec(njs_vm_t *vm, njs_webcrypto_key_t *key, njs_value_t *retval) goto fail; } - ret = njs_value_property_set(vm, retval, njs_value_arg(&string_d), - &dvalue); + ret = njs_vm_object_prop_set(vm, retval, &string_d, &dvalue); if (ret != NJS_OK) { goto fail; } @@ -1986,8 +1981,8 @@ njs_export_raw_ec(njs_vm_t *vm, njs_webcrypto_key_t *key, njs_value_t *retval) njs_assert(key->pkey != NULL); if (key->privat) { - njs_type_error(vm, "private key of \"%V\" cannot be exported " - "in \"raw\" format", njs_algorithm_string(key->alg)); + njs_vm_error(vm, "private key of \"%V\" cannot be exported " + "in \"raw\" format", njs_algorithm_string(key->alg)); return NJS_ERROR; } @@ -2022,8 +2017,8 @@ static njs_int_t njs_export_jwk_asymmetric(njs_vm_t *vm, njs_webcrypto_key_t *key, njs_value_t *retval) { - njs_int_t ret; - njs_value_t ops, extractable; + njs_int_t ret; + njs_opaque_value_t ops, extractable; njs_assert(key->pkey != NULL); @@ -2048,7 +2043,7 @@ njs_export_jwk_asymmetric(njs_vm_t *vm, njs_webcrypto_key_t *key, break; default: - njs_type_error(vm, "provided key cannot be exported as JWK"); + njs_vm_error(vm, "provided key cannot be exported as JWK"); return NJS_ERROR; } @@ -2057,15 +2052,14 @@ njs_export_jwk_asymmetric(njs_vm_t *vm, njs_webcrypto_key_t *key, return NJS_ERROR; } - ret = njs_value_property_set(vm, retval, njs_value_arg(&key_ops), &ops); + ret = njs_vm_object_prop_set(vm, retval, &key_ops, &ops); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } - njs_value_boolean_set(&extractable, key->extractable); + njs_value_boolean_set(njs_value_arg(&extractable), key->extractable); - return njs_value_property_set(vm, retval, njs_value_arg(&string_ext), - &extractable); + return njs_vm_object_prop_set(vm, retval, &string_ext, &extractable); } @@ -2074,14 +2068,12 @@ njs_export_jwk_oct(njs_vm_t *vm, njs_webcrypto_key_t *key, njs_value_t *retval) { njs_int_t ret; njs_str_t *nm; - njs_value_t k, alg, ops, extractable; + njs_opaque_value_t k, alg, ops, extractable, oct_s; njs_webcrypto_alg_t type; - static const njs_value_t oct_str = njs_string("oct"); - njs_assert(key->raw.start != NULL); - ret = njs_string_base64url(vm, &k, &key->raw); + ret = njs_string_base64url(vm, njs_value_arg(&k), &key->raw); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -2090,7 +2082,8 @@ njs_export_jwk_oct(njs_vm_t *vm, njs_webcrypto_key_t *key, njs_value_t *retval) if (key->alg->type == NJS_ALGORITHM_HMAC) { nm = &njs_webcrypto_alg_name[type][key->hash]; - (void) njs_vm_value_string_set(vm, &alg, nm->start, nm->length); + (void) njs_vm_value_string_set(vm, njs_value_arg(&alg), nm->start, + nm->length); } else { switch (key->raw.length) { @@ -2099,11 +2092,12 @@ njs_export_jwk_oct(njs_vm_t *vm, njs_webcrypto_key_t *key, njs_value_t *retval) case 32: nm = &njs_webcrypto_alg_aes_name [type - NJS_ALGORITHM_AES_GCM][(key->raw.length - 16) / 8]; - (void) njs_vm_value_string_set(vm, &alg, nm->start, nm->length); + (void) njs_vm_value_string_set(vm, njs_value_arg(&alg), nm->start, + nm->length); break; default: - njs_value_undefined_set(&alg); + njs_value_undefined_set(njs_value_arg(&alg)); break; } } @@ -2113,18 +2107,37 @@ njs_export_jwk_oct(njs_vm_t *vm, njs_webcrypto_key_t *key, njs_value_t *retval) return NJS_ERROR; } - njs_value_boolean_set(&extractable, key->extractable); + njs_value_boolean_set(njs_value_arg(&extractable), key->extractable); - ret = njs_vm_object_alloc(vm, retval, &string_kty, &oct_str, &string_k, - &k, &key_ops, &ops, &string_ext, &extractable, - NULL); + ret = njs_vm_object_alloc(vm, retval, NULL); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } - if (njs_is_defined(&alg)) { - ret = njs_value_property_set(vm, retval, njs_value_arg(&string_alg), - &alg); + njs_vm_value_string_set(vm, njs_value_arg(&oct_s), (u_char *) "oct", 3); + + ret = njs_vm_object_prop_set(vm, retval, &string_kty, &oct_s); + if (ret != NJS_OK) { + return NJS_ERROR; + } + + ret = njs_vm_object_prop_set(vm, retval, &string_k, &k); + if (ret != NJS_OK) { + return NJS_ERROR; + } + + ret = njs_vm_object_prop_set(vm, retval, &key_ops, &ops); + if (ret != NJS_OK) { + return NJS_ERROR; + } + + ret = njs_vm_object_prop_set(vm, retval, &string_ext, &extractable); + if (ret != NJS_OK) { + return NJS_ERROR; + } + + if (!njs_value_is_undefined(njs_value_arg(&alg))) { + ret = njs_vm_object_prop_set(vm, retval, &string_alg, &alg); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -2141,9 +2154,9 @@ njs_ext_export_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, BIO *bio; BUF_MEM *mem; njs_int_t ret; - njs_value_t value; njs_webcrypto_key_t *key; PKCS8_PRIV_KEY_INFO *pkcs8; + njs_opaque_value_t value; njs_webcrypto_key_format_t fmt; fmt = njs_key_format(vm, njs_arg(args, nargs, 1)); @@ -2154,19 +2167,19 @@ njs_ext_export_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, key = njs_vm_external(vm, njs_webcrypto_crypto_key_proto_id, njs_arg(args, nargs, 2)); if (njs_slow_path(key == NULL)) { - njs_type_error(vm, "\"key\" is not a CryptoKey object"); + njs_vm_error(vm, "\"key\" is not a CryptoKey object"); goto fail; } if (njs_slow_path(!(fmt & key->alg->fmt))) { - njs_type_error(vm, "unsupported key fmt \"%V\" for \"%V\" key", - njs_format_string(fmt), - njs_algorithm_string(key->alg)); + njs_vm_error(vm, "unsupported key fmt \"%V\" for \"%V\" key", + njs_format_string(fmt), + njs_algorithm_string(key->alg)); goto fail; } if (njs_slow_path(!key->extractable)) { - njs_type_error(vm, "provided key cannot be extracted"); + njs_vm_error(vm, "provided key cannot be extracted"); goto fail; } @@ -2177,7 +2190,7 @@ njs_ext_export_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, case NJS_ALGORITHM_RSA_PSS: case NJS_ALGORITHM_RSA_OAEP: case NJS_ALGORITHM_ECDSA: - ret = njs_export_jwk_asymmetric(vm, key, &value); + ret = njs_export_jwk_asymmetric(vm, key, njs_value_arg(&value)); if (njs_slow_path(ret != NJS_OK)) { goto fail; } @@ -2188,7 +2201,7 @@ njs_ext_export_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, case NJS_ALGORITHM_AES_CTR: case NJS_ALGORITHM_AES_CBC: case NJS_ALGORITHM_HMAC: - ret = njs_export_jwk_oct(vm, key, &value); + ret = njs_export_jwk_oct(vm, key, njs_value_arg(&value)); if (njs_slow_path(ret != NJS_OK)) { goto fail; } @@ -2203,8 +2216,8 @@ njs_ext_export_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, case NJS_KEY_FORMAT_PKCS8: if (!key->privat) { - njs_type_error(vm, "public key of \"%V\" cannot be exported " - "as PKCS8", njs_algorithm_string(key->alg)); + njs_vm_error(vm, "public key of \"%V\" cannot be exported " + "as PKCS8", njs_algorithm_string(key->alg)); goto fail; } @@ -2232,8 +2245,8 @@ njs_ext_export_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, BIO_get_mem_ptr(bio, &mem); - ret = njs_webcrypto_array_buffer(vm, &value, (u_char *) mem->data, - mem->length); + ret = njs_webcrypto_array_buffer(vm, njs_value_arg(&value), + (u_char *) mem->data, mem->length); BIO_free(bio); PKCS8_PRIV_KEY_INFO_free(pkcs8); @@ -2246,8 +2259,8 @@ njs_ext_export_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, case NJS_KEY_FORMAT_SPKI: if (key->privat) { - njs_type_error(vm, "private key of \"%V\" cannot be exported " - "as SPKI", njs_algorithm_string(key->alg)); + njs_vm_error(vm, "private key of \"%V\" cannot be exported " + "as SPKI", njs_algorithm_string(key->alg)); goto fail; } @@ -2267,8 +2280,8 @@ njs_ext_export_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, BIO_get_mem_ptr(bio, &mem); - ret = njs_webcrypto_array_buffer(vm, &value, (u_char *) mem->data, - mem->length); + ret = njs_webcrypto_array_buffer(vm, njs_value_arg(&value), + (u_char *) mem->data, mem->length); BIO_free(bio); @@ -2281,7 +2294,7 @@ njs_ext_export_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, case NJS_KEY_FORMAT_RAW: default: if (key->alg->type == NJS_ALGORITHM_ECDSA) { - ret = njs_export_raw_ec(vm, key, &value); + ret = njs_export_raw_ec(vm, key, njs_value_arg(&value)); if (njs_slow_path(ret != NJS_OK)) { goto fail; } @@ -2289,8 +2302,8 @@ njs_ext_export_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, break; } - ret = njs_vm_value_array_buffer_set(vm, &value, key->raw.start, - key->raw.length); + ret = njs_vm_value_array_buffer_set(vm, njs_value_arg(&value), + key->raw.start, key->raw.length); if (njs_slow_path(ret != NJS_OK)) { goto fail; } @@ -2314,14 +2327,15 @@ njs_ext_generate_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, unsigned usage; njs_int_t ret; njs_bool_t extractable; - njs_value_t value, pub, priv, *aobject; + njs_value_t *aobject, *val; EVP_PKEY_CTX *ctx; njs_webcrypto_key_t *key, *keypub; + njs_opaque_value_t value, pub, priv; njs_webcrypto_algorithm_t *alg; - static const njs_value_t string_ml = njs_string("modulusLength"); - static const njs_value_t string_priv = njs_string("privateKey"); - static const njs_value_t string_pub = njs_string("publicKey"); + static const njs_str_t string_ml = njs_str("modulusLength"); + static const njs_str_t string_priv = njs_str("privateKey"); + static const njs_str_t string_pub = njs_str("publicKey"); ctx = NULL; @@ -2344,8 +2358,8 @@ njs_ext_generate_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } if (njs_slow_path(usage & ~alg->usage)) { - njs_type_error(vm, "unsupported key usage for \"%V\" key", - njs_algorithm_string(alg)); + njs_vm_error(vm, "unsupported key usage for \"%V\" key", + njs_algorithm_string(alg)); goto fail; } @@ -2358,14 +2372,13 @@ njs_ext_generate_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, goto fail; } - ret = njs_value_property(vm, aobject, njs_value_arg(&string_ml), - &value); - if (njs_slow_path(ret == NJS_ERROR)) { + val = njs_vm_object_prop(vm, aobject, &string_ml, &value); + if (njs_slow_path(val == NULL)) { goto fail; } - if (!njs_is_number(&value)) { - njs_type_error(vm, "\"modulusLength\" is not a number"); + if (!njs_value_is_number(val)) { + njs_vm_error(vm, "\"modulusLength\" is not a number"); goto fail; } @@ -2380,7 +2393,7 @@ njs_ext_generate_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, goto fail; } - if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, njs_number(&value)) <= 0) { + if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, njs_value_number(val)) <= 0) { njs_webcrypto_error(vm, "EVP_PKEY_CTX_set_rsa_keygen_bits() " "failed"); goto fail; @@ -2415,20 +2428,31 @@ njs_ext_generate_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, ? NJS_KEY_USAGE_ENCRYPT : NJS_KEY_USAGE_VERIFY; - ret = njs_vm_external_create(vm, &priv, + ret = njs_vm_external_create(vm, njs_value_arg(&priv), njs_webcrypto_crypto_key_proto_id, key, 0); if (njs_slow_path(ret != NJS_OK)) { goto fail; } - ret = njs_vm_external_create(vm, &pub, + ret = njs_vm_external_create(vm, njs_value_arg(&pub), njs_webcrypto_crypto_key_proto_id, keypub, 0); if (njs_slow_path(ret != NJS_OK)) { goto fail; } - ret = njs_vm_object_alloc(vm, &value, &string_priv, &priv, &string_pub, - &pub, NULL); + ret = njs_vm_object_alloc(vm, njs_value_arg(&value), NULL); + if (ret != NJS_OK) { + goto fail; + } + + ret = njs_vm_object_prop_set(vm, njs_value_arg(&value), &string_priv, + &priv); + if (ret != NJS_OK) { + goto fail; + } + + ret = njs_vm_object_prop_set(vm, njs_value_arg(&value), &string_pub, + &pub); if (ret != NJS_OK) { goto fail; } @@ -2484,20 +2508,31 @@ njs_ext_generate_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, keypub->curve = key->curve; keypub->usage = NJS_KEY_USAGE_VERIFY; - ret = njs_vm_external_create(vm, &priv, + ret = njs_vm_external_create(vm, njs_value_arg(&priv), njs_webcrypto_crypto_key_proto_id, key, 0); if (njs_slow_path(ret != NJS_OK)) { goto fail; } - ret = njs_vm_external_create(vm, &pub, + ret = njs_vm_external_create(vm, njs_value_arg(&pub), njs_webcrypto_crypto_key_proto_id, keypub, 0); if (njs_slow_path(ret != NJS_OK)) { goto fail; } - ret = njs_vm_object_alloc(vm, &value, &string_priv, &priv, &string_pub, - &pub, NULL); + ret = njs_vm_object_alloc(vm, njs_value_arg(&value), NULL); + if (ret != NJS_OK) { + goto fail; + } + + ret = njs_vm_object_prop_set(vm, njs_value_arg(&value), &string_priv, + &priv); + if (ret != NJS_OK) { + goto fail; + } + + ret = njs_vm_object_prop_set(vm, njs_value_arg(&value), &string_pub, + &pub); if (ret != NJS_OK) { goto fail; } @@ -2518,27 +2553,24 @@ njs_ext_generate_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, key->raw.length = EVP_MD_size(njs_algorithm_hash_digest(key->hash)); } else { - ret = njs_value_property(vm, aobject, njs_value_arg(&string_length), - &value); - if (njs_slow_path(ret == NJS_ERROR)) { - goto fail; - } - - key->raw.length = njs_number(&value) / 8; - - if (key->raw.length != 16 - && key->raw.length != 24 - && key->raw.length != 32) - { - njs_type_error(vm, "length for \"%V\" key should be one of " - "128, 192, 256", njs_algorithm_string(alg)); - goto fail; + val = njs_vm_object_prop(vm, aobject, &string_length, &value); + if (val != NULL) { + key->raw.length = njs_value_number(val) / 8; + + if (key->raw.length != 16 + && key->raw.length != 24 + && key->raw.length != 32) + { + njs_vm_error(vm, "length for \"%V\" key should be one of " + "128, 192, 256", njs_algorithm_string(alg)); + goto fail; + } } } key->raw.start = njs_mp_alloc(njs_vm_memory_pool(vm), key->raw.length); if (njs_slow_path(key->raw.start == NULL)) { - njs_memory_error(vm); + njs_vm_memory_error(vm); goto fail; } @@ -2547,7 +2579,7 @@ njs_ext_generate_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, goto fail; } - ret = njs_vm_external_create(vm, &value, + ret = njs_vm_external_create(vm, njs_value_arg(&value), njs_webcrypto_crypto_key_proto_id, key, 0); if (njs_slow_path(ret != NJS_OK)) { goto fail; @@ -2556,8 +2588,8 @@ njs_ext_generate_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, break; default: - njs_internal_error(vm, "not implemented generateKey" - "algorithm: \"%V\"", njs_algorithm_string(alg)); + njs_vm_error(vm, "not implemented generateKey" + "algorithm: \"%V\"", njs_algorithm_string(alg)); return NJS_ERROR; } @@ -2574,13 +2606,13 @@ fail: static BIGNUM * -njs_import_base64url_bignum(njs_vm_t *vm, njs_value_t *value) +njs_import_base64url_bignum(njs_vm_t *vm, njs_opaque_value_t *value) { njs_int_t ret; njs_str_t data, decoded; u_char buf[512]; - ret = njs_vm_value_to_bytes(vm, &data, value); + ret = njs_vm_value_to_bytes(vm, &data, njs_value_arg(value)); if (njs_slow_path(ret != NJS_OK)) { return NULL; } @@ -2609,63 +2641,58 @@ njs_import_jwk_rsa(njs_vm_t *vm, njs_value_t *jwk, njs_webcrypto_key_t *key) unsigned usage; EVP_PKEY *pkey; njs_int_t ret; - njs_value_t n, e, d, p, q, dp, dq, qi, value; + njs_value_t *val; + njs_opaque_value_t n, e, d, p, q, dp, dq, qi, value; njs_webcrypto_entry_t *w; - ret = njs_value_property(vm, jwk, njs_value_arg(&string_n), &n); - if (njs_slow_path(ret == NJS_ERROR)) { - return NULL; + val = njs_vm_object_prop(vm, jwk, &string_n, &n); + if (njs_slow_path(val == NULL)) { + goto fail0; } - ret = njs_value_property(vm, jwk, njs_value_arg(&string_e), &e); - if (njs_slow_path(ret == NJS_ERROR)) { - return NULL; + val = njs_vm_object_prop(vm, jwk, &string_e, &e); + if (njs_slow_path(val == NULL)) { + goto fail0; } - ret = njs_value_property(vm, jwk, njs_value_arg(&string_d), &d); - if (njs_slow_path(ret == NJS_ERROR)) { - return NULL; + val = njs_vm_object_prop(vm, jwk, &string_d, &d); + if (njs_slow_path(val == NULL)) { + njs_value_undefined_set(njs_value_arg(&d)); } - if (!njs_value_is_string(&n) - || !njs_value_is_string(&e) - || (!njs_value_is_undefined(&d) && !njs_value_is_string(&d))) + if (!njs_value_is_string(njs_value_arg(&n)) + || !njs_value_is_string(njs_value_arg(&e)) + || (!njs_value_is_undefined(njs_value_arg(&d)) + && !njs_value_is_string(njs_value_arg(&d)))) { - njs_type_error(vm, "Invalid JWK RSA key"); +fail0: + njs_vm_error(vm, "Invalid JWK RSA key"); return NULL; } - key->privat = njs_value_is_string(&d); - - ret = njs_value_property(vm, jwk, njs_value_arg(&key_ops), &value); - if (njs_slow_path(ret == NJS_ERROR)) { - return NULL; - } + key->privat = njs_value_is_string(njs_value_arg(&d)); - if (njs_is_defined(&value)) { - ret = njs_key_usage(vm, &value, &usage); + val = njs_vm_object_prop(vm, jwk, &key_ops, &value); + if (val != NULL && !njs_value_is_undefined(val)){ + ret = njs_key_usage(vm, val, &usage); if (njs_slow_path(ret != NJS_OK)) { return NULL; } if ((key->usage & usage) != key->usage) { - njs_type_error(vm, "Key operations and usage mismatch"); + njs_vm_error(vm, "Key operations and usage mismatch"); return NULL; } } - ret = njs_value_property(vm, jwk, njs_value_arg(&string_alg), &value); - if (njs_slow_path(ret == NJS_ERROR)) { - return NULL; - } - - if (njs_is_defined(&value)) { - ret = njs_value_to_string(vm, &value, &value); + val = njs_vm_object_prop(vm, jwk, &string_alg, &value); + if (val != NULL && !njs_value_is_undefined(val)){ + ret = njs_value_to_string(vm, val, val); if (njs_slow_path(ret != NJS_OK)) { return NULL; } - njs_string_get(&value, &alg); + njs_value_string_get(val, &alg); for (w = &njs_webcrypto_alg_hash[0]; w->name.length != 0; w++) { if (njs_strstr_eq(&alg, &w->name)) { @@ -2676,13 +2703,12 @@ njs_import_jwk_rsa(njs_vm_t *vm, njs_value_t *jwk, njs_webcrypto_key_t *key) } if (key->extractable) { - ret = njs_value_property(vm, jwk, njs_value_arg(&string_ext), &value); - if (njs_slow_path(ret == NJS_ERROR)) { - return NULL; - } - - if (njs_is_defined(&value) && !njs_value_bool(&value)) { - njs_type_error(vm, "JWK RSA is not extractable"); + val = njs_vm_object_prop(vm, jwk, &string_ext, &value); + if (val != NULL + && !njs_value_is_undefined(val) + && !njs_value_bool(val)) + { + njs_vm_error(vm, "JWK RSA is not extractable"); return NULL; } } @@ -2715,39 +2741,40 @@ njs_import_jwk_rsa(njs_vm_t *vm, njs_value_t *jwk, njs_webcrypto_key_t *key) goto done; } - ret = njs_value_property(vm, jwk, njs_value_arg(&string_p), &p); - if (njs_slow_path(ret == NJS_ERROR)) { - goto fail; + val = njs_vm_object_prop(vm, jwk, &string_p, &p); + if (njs_slow_path(val == NULL)) { + goto fail1; } - ret = njs_value_property(vm, jwk, njs_value_arg(&string_q), &q); - if (njs_slow_path(ret == NJS_ERROR)) { - goto fail; + val = njs_vm_object_prop(vm, jwk, &string_q, &q); + if (njs_slow_path(val == NULL)) { + goto fail1; } - ret = njs_value_property(vm, jwk, njs_value_arg(&string_dp), &dp); - if (njs_slow_path(ret == NJS_ERROR)) { - goto fail; + val = njs_vm_object_prop(vm, jwk, &string_dp, &dp); + if (njs_slow_path(val == NULL)) { + goto fail1; } - ret = njs_value_property(vm, jwk, njs_value_arg(&string_dq), &dq); - if (njs_slow_path(ret == NJS_ERROR)) { - goto fail; + val = njs_vm_object_prop(vm, jwk, &string_dq, &dq); + if (njs_slow_path(val == NULL)) { + goto fail1; } - ret = njs_value_property(vm, jwk, njs_value_arg(&string_qi), &qi); - if (njs_slow_path(ret == NJS_ERROR)) { - goto fail; + val = njs_vm_object_prop(vm, jwk, &string_qi, &qi); + if (njs_slow_path(val == NULL)) { + goto fail1; } - if (!njs_value_is_string(&d) - || !njs_value_is_string(&p) - || !njs_value_is_string(&q) - || !njs_value_is_string(&dp) - || !njs_value_is_string(&dq) - || !njs_value_is_string(&qi)) + if (!njs_value_is_string(njs_value_arg(&d)) + || !njs_value_is_string(njs_value_arg(&p)) + || !njs_value_is_string(njs_value_arg(&q)) + || !njs_value_is_string(njs_value_arg(&dp)) + || !njs_value_is_string(njs_value_arg(&dq)) + || !njs_value_is_string(njs_value_arg(&qi))) { - njs_type_error(vm, "Invalid JWK RSA key"); +fail1: + njs_vm_error(vm, "Invalid JWK RSA key"); goto fail; } @@ -2902,7 +2929,8 @@ njs_import_jwk_ec(njs_vm_t *vm, njs_value_t *jwk, njs_webcrypto_key_t *key) EVP_PKEY *pkey; njs_str_t name; njs_int_t ret; - njs_value_t x, y, d, value; + njs_value_t *val; + njs_opaque_value_t x, y, d, value; njs_webcrypto_entry_t *e; ec = NULL; @@ -2910,77 +2938,73 @@ njs_import_jwk_ec(njs_vm_t *vm, njs_value_t *jwk, njs_webcrypto_key_t *key) y_bn = NULL; d_bn = NULL; - ret = njs_value_property(vm, jwk, njs_value_arg(&string_x), &x); - if (njs_slow_path(ret == NJS_ERROR)) { - return NULL; + val = njs_vm_object_prop(vm, jwk, &string_x, &x); + if (njs_slow_path(val == NULL)) { + goto fail0; } - ret = njs_value_property(vm, jwk, njs_value_arg(&string_y), &y); - if (njs_slow_path(ret == NJS_ERROR)) { - return NULL; + val = njs_vm_object_prop(vm, jwk, &string_y, &y); + if (njs_slow_path(val == NULL)) { + goto fail0; } - ret = njs_value_property(vm, jwk, njs_value_arg(&string_d), &d); - if (njs_slow_path(ret == NJS_ERROR)) { - return NULL; + val = njs_vm_object_prop(vm, jwk, &string_d, &d); + if (njs_slow_path(val == NULL)) { + njs_value_undefined_set(njs_value_arg(&d)); } - if (!njs_value_is_string(&x) - || !njs_value_is_string(&y) - || (!njs_value_is_undefined(&d) && !njs_value_is_string(&d))) + if (!njs_value_is_string(njs_value_arg(&x)) + || !njs_value_is_string(njs_value_arg(&y)) + || (!njs_value_is_undefined(njs_value_arg(&d)) + && !njs_value_is_string(njs_value_arg(&d)))) { - njs_type_error(vm, "Invalid JWK EC key"); +fail0: + njs_vm_error(vm, "Invalid JWK EC key"); return NULL; } - key->privat = njs_value_is_string(&d); + key->privat = njs_value_is_string(njs_value_arg(&d)); - ret = njs_value_property(vm, jwk, njs_value_arg(&key_ops), &value); - if (njs_slow_path(ret == NJS_ERROR)) { - return NULL; - } - - if (njs_is_defined(&value)) { - ret = njs_key_usage(vm, &value, &usage); + val = njs_vm_object_prop(vm, jwk, &key_ops, &value); + if (val != NULL && !njs_value_is_undefined(val)) { + ret = njs_key_usage(vm, val, &usage); if (njs_slow_path(ret != NJS_OK)) { return NULL; } if ((key->usage & usage) != key->usage) { - njs_type_error(vm, "Key operations and usage mismatch"); + njs_vm_error(vm, "Key operations and usage mismatch"); return NULL; } } if (key->extractable) { - ret = njs_value_property(vm, jwk, njs_value_arg(&string_ext), &value); - if (njs_slow_path(ret == NJS_ERROR)) { + val = njs_vm_object_prop(vm, jwk, &string_ext, &value); + if (val != NULL + && !njs_value_is_undefined(val) + && !njs_value_bool(val)) + { + njs_vm_error(vm, "JWK EC is not extractable"); return NULL; } - - if (njs_is_defined(&value) && !njs_value_bool(&value)) { - njs_type_error(vm, "JWK EC is not extractable"); - return NULL; - } - } - - ret = njs_value_property(vm, jwk, njs_value_arg(&string_crv), &value); - if (njs_slow_path(ret == NJS_ERROR)) { - return NULL; } curve = 0; - njs_string_get(&value, &name); - for (e = &njs_webcrypto_curve[0]; e->name.length != 0; e++) { - if (njs_strstr_eq(&name, &e->name)) { - curve = e->value; - break; + val = njs_vm_object_prop(vm, jwk, &string_crv, &value); + if (val != NULL && !njs_value_is_undefined(val)) { + njs_value_string_get(val, &name); + + for (e = &njs_webcrypto_curve[0]; e->name.length != 0; e++) { + if (njs_strstr_eq(&name, &e->name)) { + curve = e->value; + break; + } } } if (curve != key->curve) { - njs_type_error(vm, "JWK EC curve mismatch"); + njs_vm_error(vm, "JWK EC curve mismatch"); return NULL; } @@ -3076,7 +3100,8 @@ njs_import_jwk_oct(njs_vm_t *vm, njs_value_t *jwk, njs_webcrypto_key_t *key) unsigned usage; njs_int_t ret; njs_str_t *a, alg, b64; - njs_value_t value; + njs_value_t *val; + njs_opaque_value_t value; njs_webcrypto_alg_t type; njs_webcrypto_entry_t *w; @@ -3088,37 +3113,29 @@ njs_import_jwk_oct(njs_vm_t *vm, njs_value_t *jwk, njs_webcrypto_key_t *key) { njs_null_str, 0 } }; - ret = njs_value_property(vm, jwk, njs_value_arg(&string_k), &value); - if (njs_slow_path(ret == NJS_ERROR)) { - return NJS_ERROR; - } - - if (!njs_value_is_string(&value)) { - njs_type_error(vm, "Invalid JWK oct key"); + val = njs_vm_object_prop(vm, jwk, &string_k, &value); + if (njs_slow_path(val == NULL || !njs_value_is_string(val))) { + njs_vm_error(vm, "Invalid JWK oct key"); return NJS_ERROR; } - njs_string_get(&value, &b64); + njs_value_string_get(val, &b64); (void) njs_decode_base64url_length(&b64, &key->raw.length); key->raw.start = njs_mp_alloc(njs_vm_memory_pool(vm), key->raw.length); if (njs_slow_path(key->raw.start == NULL)) { - njs_memory_error(vm); + njs_vm_memory_error(vm); return NJS_ERROR; } njs_decode_base64url(&key->raw, &b64); - ret = njs_value_property(vm, jwk, njs_value_arg(&string_alg), &value); - if (njs_slow_path(ret == NJS_ERROR)) { - return NJS_ERROR; - } - size = 16; - if (njs_value_is_string(&value)) { - njs_string_get(&value, &alg); + val = njs_vm_object_prop(vm, jwk, &string_alg, &value); + if (val != NULL && njs_value_is_string(val)) { + njs_value_string_get(val, &alg); if (key->alg->type == NJS_ALGORITHM_HMAC) { for (w = &hashes[0]; w->name.length != 0; w++) { @@ -3140,7 +3157,7 @@ njs_import_jwk_oct(njs_vm_t *vm, njs_value_t *jwk, njs_webcrypto_key_t *key) } } - njs_type_error(vm, "unexpected \"alg\" value \"%V\" for JWK key", &alg); + njs_vm_error(vm, "unexpected \"alg\" value \"%V\" for JWK key", &alg); return NJS_ERROR; } @@ -3148,37 +3165,32 @@ done: if (key->alg->type != NJS_ALGORITHM_HMAC) { if (key->raw.length != size) { - njs_type_error(vm, "key size and \"alg\" value \"%V\" mismatch", - &alg); + njs_vm_error(vm, "key size and \"alg\" value \"%V\" mismatch", + &alg); return NJS_ERROR; } } - ret = njs_value_property(vm, jwk, njs_value_arg(&key_ops), &value); - if (njs_slow_path(ret == NJS_ERROR)) { - return NJS_ERROR; - } - - if (njs_is_defined(&value)) { - ret = njs_key_usage(vm, &value, &usage); + val = njs_vm_object_prop(vm, jwk, &key_ops, &value); + if (val != NULL && !njs_value_is_undefined(val)) { + ret = njs_key_usage(vm, val, &usage); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } if ((key->usage & usage) != key->usage) { - njs_type_error(vm, "Key operations and usage mismatch"); + njs_vm_error(vm, "Key operations and usage mismatch"); return NJS_ERROR; } } if (key->extractable) { - ret = njs_value_property(vm, jwk, njs_value_arg(&string_ext), &value); - if (njs_slow_path(ret == NJS_ERROR)) { - return NJS_ERROR; - } - - if (njs_is_defined(&value) && !njs_value_bool(&value)) { - njs_type_error(vm, "JWK oct is not extractable"); + val = njs_vm_object_prop(vm, jwk, &string_ext, &value); + if (val != NULL + && !njs_value_is_undefined(val) + && !njs_value_bool(val)) + { + njs_vm_error(vm, "JWK oct is not extractable"); return NJS_ERROR; } } @@ -3203,13 +3215,14 @@ njs_ext_import_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, EVP_PKEY *pkey; njs_int_t ret; njs_str_t key_data, kty; - njs_value_t value, *options, *jwk; + njs_value_t *options, *jwk, *val; const u_char *start; #if (OPENSSL_VERSION_NUMBER < 0x30000000L) const EC_GROUP *group; #endif njs_webcrypto_key_t *key; PKCS8_PRIV_KEY_INFO *pkcs8; + njs_opaque_value_t value; njs_webcrypto_hash_t hash; njs_webcrypto_algorithm_t *alg; njs_webcrypto_key_format_t fmt; @@ -3230,9 +3243,9 @@ njs_ext_import_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } if (njs_slow_path(!(fmt & alg->fmt))) { - njs_type_error(vm, "unsupported key fmt \"%V\" for \"%V\" key", - njs_format_string(fmt), - njs_algorithm_string(alg)); + njs_vm_error(vm, "unsupported key fmt \"%V\" for \"%V\" key", + njs_format_string(fmt), + njs_algorithm_string(alg)); goto fail; } @@ -3242,8 +3255,8 @@ njs_ext_import_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } if (njs_slow_path(usage & ~alg->usage)) { - njs_type_error(vm, "unsupported key usage for \"%V\" key", - njs_algorithm_string(alg)); + njs_vm_error(vm, "unsupported key usage for \"%V\" key", + njs_algorithm_string(alg)); goto fail; } @@ -3314,16 +3327,16 @@ njs_ext_import_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, case NJS_KEY_FORMAT_JWK: jwk = njs_arg(args, nargs, 2); if (!njs_value_is_object(jwk)) { - njs_type_error(vm, "invalid JWK key data: object value expected"); + njs_vm_error(vm, "invalid JWK key data: object value expected"); goto fail; } - ret = njs_value_property(vm, jwk, njs_value_arg(&string_kty), &value); - if (njs_slow_path(ret == NJS_ERROR)) { - goto fail; + val = njs_vm_object_prop(vm, jwk, &string_kty, &value); + if (njs_slow_path(val == NULL)) { + val = njs_value_arg(&njs_value_undefined); } - ret = njs_vm_value_to_bytes(vm, &kty, &value); + ret = njs_vm_value_to_bytes(vm, &kty, val); if (njs_slow_path(ret != NJS_OK)) { goto fail; } @@ -3352,7 +3365,7 @@ njs_ext_import_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } } else { - njs_type_error(vm, "invalid JWK key type: %V", &kty); + njs_vm_error(vm, "invalid JWK key type: %V", &kty); goto fail; } @@ -3391,7 +3404,7 @@ njs_ext_import_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } if (key->hash != NJS_HASH_UNSET && key->hash != hash) { - njs_type_error(vm, "RSA JWK hash mismatch"); + njs_vm_error(vm, "RSA JWK hash mismatch"); goto fail; } @@ -3406,8 +3419,8 @@ njs_ext_import_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } if (key->usage & mask) { - njs_type_error(vm, "key usage mismatch for \"%V\" key", - njs_algorithm_string(alg)); + njs_vm_error(vm, "key usage mismatch for \"%V\" key", + njs_algorithm_string(alg)); goto fail; } @@ -3466,8 +3479,8 @@ njs_ext_import_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, mask = key->privat ? ~NJS_KEY_USAGE_SIGN : ~NJS_KEY_USAGE_VERIFY; if (key->usage & mask) { - njs_type_error(vm, "key usage mismatch for \"%V\" key", - njs_algorithm_string(alg)); + njs_vm_error(vm, "key usage mismatch for \"%V\" key", + njs_algorithm_string(alg)); goto fail; } @@ -3493,7 +3506,7 @@ njs_ext_import_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } if (key->hash != NJS_HASH_UNSET && key->hash != hash) { - njs_type_error(vm, "HMAC JWK hash mismatch"); + njs_vm_error(vm, "HMAC JWK hash mismatch"); goto fail; } } @@ -3511,7 +3524,7 @@ njs_ext_import_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, break; default: - njs_type_error(vm, "AES Invalid key length"); + njs_vm_error(vm, "AES Invalid key length"); goto fail; } @@ -3527,8 +3540,8 @@ njs_ext_import_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, break; } - ret = njs_vm_external_create(vm, &value, njs_webcrypto_crypto_key_proto_id, - key, 0); + ret = njs_vm_external_create(vm, njs_value_arg(&value), + njs_webcrypto_crypto_key_proto_id, key, 0); if (njs_slow_path(ret != NJS_OK)) { goto fail; } @@ -3549,12 +3562,13 @@ static njs_int_t njs_set_rsa_padding(njs_vm_t *vm, njs_value_t *options, EVP_PKEY *pkey, EVP_PKEY_CTX *ctx, njs_webcrypto_alg_t type) { - int padding; - int64_t salt_length; - njs_int_t ret; - njs_value_t value; + int padding; + int64_t salt_length; + njs_int_t ret; + njs_value_t *value; + njs_opaque_value_t lvalue; - static const njs_value_t string_saltl = njs_string("saltLength"); + static const njs_str_t string_saltl = njs_str("saltLength"); if (type == NJS_ALGORITHM_ECDSA) { return NJS_OK; @@ -3569,18 +3583,13 @@ njs_set_rsa_padding(njs_vm_t *vm, njs_value_t *options, EVP_PKEY *pkey, } if (padding == RSA_PKCS1_PSS_PADDING) { - ret = njs_value_property(vm, options, njs_value_arg(&string_saltl), - &value); - if (njs_slow_path(ret != NJS_OK)) { - if (ret == NJS_DECLINED) { - njs_type_error(vm, "RSA-PSS algorithm.saltLength " - "is not provided"); - } - + value = njs_vm_object_prop(vm, options, &string_saltl, &lvalue); + if (njs_slow_path(value == NULL)) { + njs_vm_error(vm, "RSA-PSS algorithm.saltLength is not provided"); return NJS_ERROR; } - ret = njs_value_to_integer(vm, &value, &salt_length); + ret = njs_value_to_integer(vm, value, &salt_length); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -3778,9 +3787,10 @@ njs_ext_sign(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_int_t ret; njs_str_t data, sig; EVP_MD_CTX *mctx; - njs_value_t value, *options; + njs_value_t *options; EVP_PKEY_CTX *pctx; const EVP_MD *md; + njs_opaque_value_t result; njs_webcrypto_key_t *key; njs_webcrypto_hash_t hash; njs_webcrypto_algorithm_t *alg; @@ -3798,21 +3808,21 @@ njs_ext_sign(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, key = njs_vm_external(vm, njs_webcrypto_crypto_key_proto_id, njs_arg(args, nargs, 2)); if (njs_slow_path(key == NULL)) { - njs_type_error(vm, "\"key\" is not a CryptoKey object"); + njs_vm_error(vm, "\"key\" is not a CryptoKey object"); goto fail; } mask = verify ? NJS_KEY_USAGE_VERIFY : NJS_KEY_USAGE_SIGN; if (njs_slow_path(!(key->usage & mask))) { - njs_type_error(vm, "provide key does not support \"sign\" operation"); + njs_vm_error(vm, "provide key does not support \"sign\" operation"); goto fail; } if (njs_slow_path(key->alg != alg)) { - njs_type_error(vm, "cannot %s using \"%V\" with \"%V\" key", - verify ? "verify" : "sign", - njs_algorithm_string(key->alg), - njs_algorithm_string(alg)); + njs_vm_error(vm, "cannot %s using \"%V\" with \"%V\" key", + verify ? "verify" : "sign", + njs_algorithm_string(key->alg), + njs_algorithm_string(alg)); goto fail; } @@ -3855,7 +3865,7 @@ njs_ext_sign(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, if (!verify) { dst = njs_mp_alloc(njs_vm_memory_pool(vm), m_len); if (njs_slow_path(dst == NULL)) { - njs_memory_error(vm); + njs_vm_memory_error(vm); goto fail; } @@ -3910,7 +3920,7 @@ njs_ext_sign(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, olen = EVP_PKEY_size(key->pkey); dst = njs_mp_zalloc(njs_vm_memory_pool(vm), olen); if (njs_slow_path(dst == NULL)) { - njs_memory_error(vm); + njs_vm_memory_error(vm); goto fail; } @@ -3987,16 +3997,17 @@ njs_ext_sign(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } if (!verify) { - ret = njs_vm_value_array_buffer_set(vm, &value, dst, outlen); + ret = njs_vm_value_array_buffer_set(vm, njs_value_arg(&result), dst, + outlen); if (njs_slow_path(ret != NJS_OK)) { goto fail; } } else { - njs_set_boolean(&value, ret != 0); + njs_value_boolean_set(njs_value_arg(&result), ret != 0); } - return njs_webcrypto_result(vm, &value, NJS_OK, retval); + return njs_webcrypto_result(vm, &result, NJS_OK, retval); fail: @@ -4016,7 +4027,7 @@ static njs_int_t njs_ext_unwrap_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { - njs_internal_error(vm, "\"unwrapKey\" not implemented"); + njs_vm_error(vm, "\"unwrapKey\" not implemented"); return NJS_ERROR; } @@ -4025,7 +4036,7 @@ static njs_int_t njs_ext_wrap_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { - njs_internal_error(vm, "\"wrapKey\" not implemented"); + njs_vm_error(vm, "\"wrapKey\" not implemented"); return NJS_ERROR; } @@ -4046,7 +4057,7 @@ njs_ext_get_random_values(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } if (njs_slow_path(fill.length > 65536)) { - njs_type_error(vm, "requested length exceeds 65536 bytes"); + njs_vm_error(vm, "requested length exceeds 65536 bytes"); return NJS_ERROR; } @@ -4081,13 +4092,13 @@ njs_webcrypto_key_alloc(njs_vm_t *vm, njs_webcrypto_algorithm_t *alg, key = njs_mp_zalloc(njs_vm_memory_pool(vm), sizeof(njs_webcrypto_key_t)); if (njs_slow_path(key == NULL)) { - njs_memory_error(vm); + njs_vm_memory_error(vm); return NULL; } cln = njs_mp_cleanup_add(njs_vm_memory_pool(vm), 0); if (cln == NULL) { - njs_memory_error(vm); + njs_vm_memory_error(vm); return NULL; } @@ -4107,15 +4118,15 @@ njs_key_format(njs_vm_t *vm, njs_value_t *value) { njs_int_t ret; njs_str_t format; - njs_value_t string; + njs_opaque_value_t string; njs_webcrypto_entry_t *e; - ret = njs_value_to_string(vm, &string, value); + ret = njs_value_to_string(vm, njs_value_arg(&string), value); if (njs_slow_path(ret != NJS_OK)) { return NJS_KEY_FORMAT_UNKNOWN; } - njs_string_get(&string, &format); + njs_value_string_get(njs_value_arg(&string), &format); for (e = &njs_webcrypto_format[0]; e->name.length != 0; e++) { if (njs_strstr_eq(&format, &e->name)) { @@ -4123,7 +4134,7 @@ njs_key_format(njs_vm_t *vm, njs_value_t *value) } } - njs_type_error(vm, "unknown key format: \"%V\"", &format); + njs_vm_error(vm, "unknown key format: \"%V\"", &format); return NJS_KEY_FORMAT_UNKNOWN; } @@ -4151,17 +4162,17 @@ njs_key_usage_array_handler(njs_vm_t *vm, njs_iterator_args_t *args, unsigned *mask; njs_str_t u; njs_int_t ret; - njs_value_t usage; + njs_opaque_value_t usage; njs_webcrypto_entry_t *e; njs_value_assign(&usage, value); - ret = njs_value_to_string(vm, &usage, &usage); + ret = njs_value_to_string(vm, njs_value_arg(&usage), njs_value_arg(&usage)); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } - njs_string_get(&usage, &u); + njs_value_string_get(njs_value_arg(&usage), &u); for (e = &njs_webcrypto_usage[0]; e->name.length != 0; e++) { if (njs_strstr_eq(&u, &e->name)) { @@ -4171,7 +4182,7 @@ njs_key_usage_array_handler(njs_vm_t *vm, njs_iterator_args_t *args, } } - njs_type_error(vm, "unknown key usage: \"%V\"", &u); + njs_vm_error(vm, "unknown key usage: \"%V\"", &u); return NJS_ERROR; } @@ -4182,15 +4193,15 @@ njs_key_usage(njs_vm_t *vm, njs_value_t *value, unsigned *mask) { int64_t length; njs_int_t ret; - njs_value_t retval; + njs_opaque_value_t retval; njs_iterator_args_t args; - if (!njs_value_is_object(value)) { - njs_type_error(vm, "\"keyUsages\" argument must be an Array"); + if (!njs_value_is_array(value)) { + njs_vm_error(vm, "\"keyUsages\" argument must be an Array"); return NJS_ERROR; } - ret = njs_object_length(vm, value, &length); + ret = njs_vm_array_length(vm, value, &length); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -4202,26 +4213,26 @@ njs_key_usage(njs_vm_t *vm, njs_value_t *value, unsigned *mask) args.to = length; args.data = mask; - return njs_object_iterate(vm, &args, njs_key_usage_array_handler, - &retval); + return njs_vm_object_iterate(vm, &args, njs_key_usage_array_handler, + njs_value_arg(&retval)); } static njs_int_t -njs_key_ops(njs_vm_t *vm, njs_value_t *retval, unsigned mask) +njs_key_ops(njs_vm_t *vm, njs_opaque_value_t *retval, unsigned mask) { njs_int_t ret; njs_value_t *value; njs_webcrypto_entry_t *e; - ret = njs_vm_array_alloc(vm, retval, 4); + ret = njs_vm_array_alloc(vm, njs_value_arg(retval), 4); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } for (e = &njs_webcrypto_usage[0]; e->name.length != 0; e++) { if (mask & e->value) { - value = njs_vm_array_push(vm, retval); + value = njs_vm_array_push(vm, njs_value_arg(retval)); if (value == NULL) { return NJS_ERROR; } @@ -4243,20 +4254,17 @@ njs_key_algorithm(njs_vm_t *vm, njs_value_t *options) { njs_int_t ret; njs_str_t a; - njs_value_t name; + njs_value_t *val; + njs_opaque_value_t name; njs_webcrypto_entry_t *e; njs_webcrypto_algorithm_t *alg; - static const njs_value_t string_name = njs_string("name"); - - if (njs_is_object(options)) { - ret = njs_value_property(vm, options, njs_value_arg(&string_name), - &name); - if (njs_slow_path(ret != NJS_OK)) { - if (ret == NJS_DECLINED) { - njs_type_error(vm, "algorithm name is not provided"); - } + static const njs_str_t string_name = njs_str("name"); + if (njs_value_is_object(options)) { + val = njs_vm_object_prop(vm, options, &string_name, &name); + if (njs_slow_path(val == NULL)) { + njs_vm_error(vm, "algorithm name is not provided"); return NULL; } @@ -4264,18 +4272,18 @@ njs_key_algorithm(njs_vm_t *vm, njs_value_t *options) njs_value_assign(&name, options); } - ret = njs_value_to_string(vm, &name, &name); + ret = njs_value_to_string(vm, njs_value_arg(&name), njs_value_arg(&name)); if (njs_slow_path(ret != NJS_OK)) { return NULL; } - njs_string_get(&name, &a); + njs_value_string_get(njs_value_arg(&name), &a); for (e = &njs_webcrypto_alg[0]; e->name.length != 0; e++) { if (njs_strstr_case_eq(&a, &e->name)) { alg = (njs_webcrypto_algorithm_t *) e->value; if (alg->usage & NJS_KEY_USAGE_UNSUPPORTED) { - njs_type_error(vm, "unsupported algorithm: \"%V\"", &a); + njs_vm_error(vm, "unsupported algorithm: \"%V\"", &a); return NULL; } @@ -4283,7 +4291,7 @@ njs_key_algorithm(njs_vm_t *vm, njs_value_t *options) } } - njs_type_error(vm, "unknown algorithm name: \"%V\"", &a); + njs_vm_error(vm, "unknown algorithm name: \"%V\"", &a); return NULL; } @@ -4312,28 +4320,28 @@ njs_algorithm_hash(njs_vm_t *vm, njs_value_t *options, { njs_int_t ret; njs_str_t name; - njs_value_t value; + njs_value_t *val; + njs_opaque_value_t value; njs_webcrypto_entry_t *e; - static const njs_value_t string_hash = njs_string("hash"); + static const njs_str_t string_hash = njs_str("hash"); - if (njs_is_object(options)) { - ret = njs_value_property(vm, options, njs_value_arg(&string_hash), - &value); - if (njs_slow_path(ret == NJS_ERROR)) { - return NJS_ERROR; + if (njs_value_is_object(options)) { + val = njs_vm_object_prop(vm, options, &string_hash, &value); + if (njs_slow_path(val == NULL)) { + njs_value_undefined_set(njs_value_arg(&value)); } } else { njs_value_assign(&value, options); } - ret = njs_value_to_string(vm, &value, &value); + ret = njs_value_to_string(vm, njs_value_arg(&value), njs_value_arg(&value)); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } - njs_string_get(&value, &name); + njs_value_string_get(njs_value_arg(&value), &name); for (e = &njs_webcrypto_hash[0]; e->name.length != 0; e++) { if (njs_strstr_eq(&name, &e->name)) { @@ -4342,7 +4350,7 @@ njs_algorithm_hash(njs_vm_t *vm, njs_value_t *options, } } - njs_type_error(vm, "unknown hash name: \"%V\"", &name); + njs_vm_error(vm, "unknown hash name: \"%V\"", &name); return NJS_ERROR; } @@ -4375,27 +4383,27 @@ njs_algorithm_curve(njs_vm_t *vm, njs_value_t *options, int *curve) { njs_int_t ret; njs_str_t name; - njs_value_t value; + njs_value_t *val; + njs_opaque_value_t value; njs_webcrypto_entry_t *e; - static const njs_value_t string_curve = njs_string("namedCurve"); + static const njs_str_t string_curve = njs_str("namedCurve"); if (*curve != 0) { return NJS_OK; } - ret = njs_value_property(vm, options, njs_value_arg(&string_curve), - &value); - if (njs_slow_path(ret != NJS_OK)) { - return ret; + val = njs_vm_object_prop(vm, options, &string_curve, &value); + if (njs_slow_path(val == NULL)) { + njs_value_undefined_set(njs_value_arg(&value)); } - ret = njs_value_to_string(vm, &value, &value); + ret = njs_value_to_string(vm, njs_value_arg(&value), njs_value_arg(&value)); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } - njs_string_get(&value, &name); + njs_value_string_get(njs_value_arg(&value), &name); for (e = &njs_webcrypto_curve[0]; e->name.length != 0; e++) { if (njs_strstr_eq(&name, &e->name)) { @@ -4404,7 +4412,7 @@ njs_algorithm_curve(njs_vm_t *vm, njs_value_t *options, int *curve) } } - njs_type_error(vm, "unknown namedCurve: \"%V\"", &name); + njs_vm_error(vm, "unknown namedCurve: \"%V\"", &name); return NJS_ERROR; } @@ -4427,15 +4435,16 @@ njs_promise_trampoline(njs_vm_t *vm, njs_value_t *args, static njs_int_t -njs_webcrypto_result(njs_vm_t *vm, njs_value_t *result, njs_int_t rc, +njs_webcrypto_result(njs_vm_t *vm, njs_opaque_value_t *result, njs_int_t rc, njs_value_t *retval) { - njs_int_t ret; - njs_value_t promise, arguments[2]; - njs_function_t *callback; - njs_vm_event_t vm_event; + njs_int_t ret; + njs_function_t *callback; + njs_vm_event_t vm_event; + njs_opaque_value_t promise, arguments[2]; - ret = njs_vm_promise_create(vm, &promise, njs_value_arg(&arguments)); + ret = njs_vm_promise_create(vm, njs_value_arg(&promise), + njs_value_arg(&arguments)); if (ret != NJS_OK) { goto error; } @@ -4484,7 +4493,7 @@ njs_webcrypto_array_buffer(njs_vm_t *vm, njs_value_t *retval, dst = njs_mp_alloc(njs_vm_memory_pool(vm), length); if (njs_slow_path(dst == NULL)) { - njs_memory_error(vm); + njs_vm_memory_error(vm); return NJS_ERROR; } diff --git a/src/njs.h b/src/njs.h index 34e95e0f..7a091e66 100644 --- a/src/njs.h +++ b/src/njs.h @@ -304,6 +304,23 @@ typedef struct { } njs_vm_opt_t; +typedef struct { + njs_function_t *function; + njs_opaque_value_t argument; + njs_opaque_value_t value; + + void *data; + + int64_t from; + int64_t to; +} njs_iterator_args_t; + + +typedef njs_int_t (*njs_iterator_handler_t)(njs_vm_t *vm, + njs_iterator_args_t *args, njs_value_t *entry, int64_t n, + njs_value_t *retval); + + NJS_EXPORT void njs_vm_opt_init(njs_vm_opt_t *options); NJS_EXPORT njs_vm_t *njs_vm_create(njs_vm_opt_t *options); NJS_EXPORT void njs_vm_destroy(njs_vm_t *vm); @@ -520,6 +537,9 @@ NJS_EXPORT njs_value_t *njs_vm_object_prop(njs_vm_t *vm, njs_value_t *value, const njs_str_t *key, njs_opaque_value_t *retval); NJS_EXPORT njs_int_t njs_vm_object_prop_set(njs_vm_t *vm, njs_value_t *value, const njs_str_t *prop, njs_opaque_value_t *setval); +NJS_EXPORT njs_int_t njs_vm_object_iterate(njs_vm_t *vm, + njs_iterator_args_t *args, njs_iterator_handler_t handler, + njs_value_t *retval); NJS_EXPORT njs_int_t njs_vm_array_alloc(njs_vm_t *vm, njs_value_t *retval, uint32_t spare); diff --git a/src/njs_iterator.h b/src/njs_iterator.h index f04fa931..3ff079b0 100644 --- a/src/njs_iterator.h +++ b/src/njs_iterator.h @@ -8,23 +8,6 @@ #define _NJS_ITERATOR_H_INCLUDED_ -typedef struct { - njs_function_t *function; - njs_opaque_value_t argument; - njs_opaque_value_t value; - - void *data; - - int64_t from; - int64_t to; -} njs_iterator_args_t; - - -typedef njs_int_t (*njs_iterator_handler_t)(njs_vm_t *vm, - njs_iterator_args_t *args, njs_value_t *entry, int64_t n, - njs_value_t *retval); - - njs_int_t njs_array_iterator_create(njs_vm_t *vm, const njs_value_t *src, njs_value_t *dst, njs_object_enum_t kind); diff --git a/src/njs_vm.c b/src/njs_vm.c index 90a17953..cf1b271b 100644 --- a/src/njs_vm.c +++ b/src/njs_vm.c @@ -1215,6 +1215,14 @@ njs_vm_array_prop(njs_vm_t *vm, njs_value_t *value, int64_t index, } +njs_int_t +njs_vm_object_iterate(njs_vm_t *vm, njs_iterator_args_t *args, + njs_iterator_handler_t handler, njs_value_t *retval) +{ + return njs_object_iterate(vm, args, handler, retval); +} + + njs_value_t * njs_vm_array_start(njs_vm_t *vm, njs_value_t *value) { diff --git a/test/harness/runTsuite.js b/test/harness/runTsuite.js index 3d826807..d9d6b48f 100644 --- a/test/harness/runTsuite.js +++ b/test/harness/runTsuite.js @@ -13,7 +13,7 @@ async function run(tlist) { } if (r.status == "rejected" && t[i].optional) { - return r.reason.toString().startsWith("InternalError: not implemented"); + return r.reason.toString().startsWith("Error: not implemented"); } return false;