njs_webcrypto_alg_t type;
unsigned usage;
unsigned fmt;
+ unsigned raw;
} njs_webcrypto_algorithm_t;
typedef struct {
njs_webcrypto_algorithm_t *alg;
+ unsigned usage;
+ njs_bool_t extractable;
+
njs_webcrypto_hash_t hash;
- int curve;
- EVP_PKEY *pkey;
- njs_str_t raw;
+ union {
+ struct {
+ EVP_PKEY *pkey;
+ njs_bool_t privat;
+ int curve;
+ } a;
+ struct {
+ njs_str_t raw;
+ } s;
+ } u;
- unsigned usage;
- njs_bool_t extractable;
- njs_bool_t privat;
} njs_webcrypto_key_t;
static njs_webcrypto_entry_t njs_webcrypto_alg[] = {
-#define njs_webcrypto_algorithm(type, usage_mask, fmt_mask) \
- (uintptr_t) & (njs_webcrypto_algorithm_t) { type, usage_mask, fmt_mask }
+#define njs_webcrypto_algorithm(type, usage, fmt, raw) \
+ (uintptr_t) & (njs_webcrypto_algorithm_t) { type, usage, fmt, raw }
{
njs_str("RSASSA-PKCS1-v1_5"),
NJS_KEY_USAGE_GENERATE_KEY,
NJS_KEY_FORMAT_PKCS8 |
NJS_KEY_FORMAT_SPKI |
- NJS_KEY_FORMAT_JWK)
+ NJS_KEY_FORMAT_JWK,
+ 0)
},
{
NJS_KEY_USAGE_GENERATE_KEY,
NJS_KEY_FORMAT_PKCS8 |
NJS_KEY_FORMAT_SPKI |
- NJS_KEY_FORMAT_JWK)
+ NJS_KEY_FORMAT_JWK,
+ 0)
},
{
NJS_KEY_USAGE_GENERATE_KEY,
NJS_KEY_FORMAT_PKCS8 |
NJS_KEY_FORMAT_SPKI |
- NJS_KEY_FORMAT_JWK)
+ NJS_KEY_FORMAT_JWK,
+ 0)
},
{
NJS_KEY_USAGE_SIGN |
NJS_KEY_USAGE_VERIFY,
NJS_KEY_FORMAT_RAW |
- NJS_KEY_FORMAT_JWK)
+ NJS_KEY_FORMAT_JWK,
+ 1)
},
{
NJS_KEY_USAGE_UNWRAP_KEY |
NJS_KEY_USAGE_GENERATE_KEY,
NJS_KEY_FORMAT_RAW |
- NJS_KEY_FORMAT_JWK)
+ NJS_KEY_FORMAT_JWK,
+ 1)
},
{
NJS_KEY_USAGE_UNWRAP_KEY |
NJS_KEY_USAGE_GENERATE_KEY,
NJS_KEY_FORMAT_RAW |
- NJS_KEY_FORMAT_JWK)
+ NJS_KEY_FORMAT_JWK,
+ 1)
},
{
NJS_KEY_USAGE_UNWRAP_KEY |
NJS_KEY_USAGE_GENERATE_KEY,
NJS_KEY_FORMAT_RAW |
- NJS_KEY_FORMAT_JWK)
+ NJS_KEY_FORMAT_JWK,
+ 1)
},
{
NJS_KEY_FORMAT_PKCS8 |
NJS_KEY_FORMAT_SPKI |
NJS_KEY_FORMAT_RAW |
- NJS_KEY_FORMAT_JWK)
+ NJS_KEY_FORMAT_JWK,
+ 0)
},
{
NJS_KEY_USAGE_DERIVE_BITS |
NJS_KEY_USAGE_GENERATE_KEY |
NJS_KEY_USAGE_UNSUPPORTED,
- NJS_KEY_FORMAT_UNKNOWN)
+ NJS_KEY_FORMAT_UNKNOWN,
+ 0)
},
{
njs_webcrypto_algorithm(NJS_ALGORITHM_PBKDF2,
NJS_KEY_USAGE_DERIVE_KEY |
NJS_KEY_USAGE_DERIVE_BITS,
- NJS_KEY_FORMAT_RAW)
+ NJS_KEY_FORMAT_RAW,
+ 1)
},
{
njs_webcrypto_algorithm(NJS_ALGORITHM_HKDF,
NJS_KEY_USAGE_DERIVE_KEY |
NJS_KEY_USAGE_DERIVE_BITS,
- NJS_KEY_FORMAT_RAW)
+ NJS_KEY_FORMAT_RAW,
+ 1)
},
{
EVP_PKEY_cipher_t cipher;
EVP_PKEY_cipher_init_t init;
- ctx = EVP_PKEY_CTX_new(key->pkey, NULL);
+ ctx = EVP_PKEY_CTX_new(key->u.a.pkey, NULL);
if (njs_slow_path(ctx == NULL)) {
njs_webcrypto_error(vm, "EVP_PKEY_CTX_new() failed");
return NJS_ERROR;
static const njs_str_t string_ad = njs_str("additionalData");
static const njs_str_t string_tl = njs_str("tagLength");
- switch (key->raw.length) {
+ switch (key->u.s.raw.length) {
case 16:
cipher = EVP_aes_128_gcm();
break;
goto fail;
}
- ret = EVP_CipherInit_ex(ctx, NULL, NULL, key->raw.start, iv.start,
+ ret = EVP_CipherInit_ex(ctx, NULL, NULL, key->u.s.raw.start, iv.start,
encrypt);
if (njs_slow_path(ret <= 0)) {
njs_webcrypto_error(vm, "EVP_%sInit_ex() failed",
static const njs_str_t string_counter = njs_str("counter");
- switch (key->raw.length) {
+ switch (key->u.s.raw.length) {
case 16:
cipher = EVP_aes_128_ctr();
break;
* during the ciphering.
* */
- ret = njs_cipher_aes_ctr128(vm, cipher, key->raw.start,
+ ret = njs_cipher_aes_ctr128(vm, cipher, key->u.s.raw.start,
data->start, data->length, iv.start, dst,
&len, encrypt);
if (njs_slow_path(ret != NJS_OK)) {
size1 = BN_get_word(left) * AES_BLOCK_SIZE;
- ret = njs_cipher_aes_ctr128(vm, cipher, key->raw.start, data->start, size1,
- iv.start, dst, &len, encrypt);
+ ret = njs_cipher_aes_ctr128(vm, cipher, key->u.s.raw.start, data->start,
+ size1, iv.start, dst, &len, encrypt);
if (njs_slow_path(ret != NJS_OK)) {
goto fail;
}
njs_counter128_reset(iv.start, (u_char *) iv2, length);
- ret = njs_cipher_aes_ctr128(vm, cipher, key->raw.start, &data->start[size1],
- data->length - size1, iv2, &dst[size1], &len2,
- encrypt);
+ ret = njs_cipher_aes_ctr128(vm, cipher, key->u.s.raw.start,
+ &data->start[size1], data->length - size1,
+ iv2, &dst[size1], &len2, encrypt);
if (njs_slow_path(ret != NJS_OK)) {
goto fail;
}
static const njs_str_t string_iv = njs_str("iv");
- switch (key->raw.length) {
+ switch (key->u.s.raw.length) {
case 16:
cipher = EVP_aes_128_cbc();
break;
return NJS_ERROR;
}
- ret = EVP_CipherInit_ex(ctx, cipher, NULL, key->raw.start, iv.start,
+ ret = EVP_CipherInit_ex(ctx, cipher, NULL, key->u.s.raw.start, iv.start,
encrypt);
if (njs_slow_path(ret <= 0)) {
njs_webcrypto_error(vm, "EVP_%SInit_ex() failed",
md = njs_algorithm_hash_digest(hash);
- ret = PKCS5_PBKDF2_HMAC((char *) key->raw.start, key->raw.length,
+ ret = PKCS5_PBKDF2_HMAC((char *) key->u.s.raw.start, key->u.s.raw.length,
salt.start, salt.length, iterations, md,
length, k);
if (njs_slow_path(ret <= 0)) {
goto free;
}
- ret = EVP_PKEY_CTX_set1_hkdf_key(pctx, key->raw.start, key->raw.length);
+ ret = EVP_PKEY_CTX_set1_hkdf_key(pctx, key->u.s.raw.start,
+ key->u.s.raw.length);
if (njs_slow_path(ret <= 0)) {
njs_webcrypto_error(vm, "EVP_PKEY_CTX_set1_hkdf_key() failed");
goto free;
}
}
- dkey->raw.start = k;
- dkey->raw.length = length;
+ dkey->u.s.raw.start = k;
+ dkey->u.s.raw.length = length;
ret = njs_vm_external_create(vm, njs_value_arg(&lvalue),
njs_webcrypto_crypto_key_proto_id,
*qi_bn;
njs_opaque_value_t nvalue, evalue, alg, rsa_s;
- rsa = njs_pkey_get_rsa_key(key->pkey);
+ rsa = njs_pkey_get_rsa_key(key->u.a.pkey);
njs_rsa_get0_key(rsa, &n_bn, &e_bn, &d_bn);
return NJS_ERROR;
}
- if (key->privat) {
+ if (key->u.a.privat) {
njs_rsa_get0_factors(rsa, &p_bn, &q_bn);
njs_rsa_get0_ctr_params(rsa, &dp_bn, &dq_bn, &qi_bn);
y_bn = NULL;
d_bn = NULL;
- ec = njs_pkey_get_ec_key(key->pkey);
+ ec = njs_pkey_get_ec_key(key->u.a.pkey);
pub = EC_KEY_get0_public_key(ec);
group = EC_KEY_get0_group(ec);
return NJS_ERROR;
}
- if (key->privat) {
+ if (key->u.a.privat) {
d_bn = EC_KEY_get0_private_key(ec);
ret = njs_export_base64url_bignum(vm, &dvalue, d_bn, group_bytes);
const EC_POINT *point;
point_conversion_form_t form;
- njs_assert(key->pkey != NULL);
+ njs_assert(key->u.a.pkey != NULL);
- if (key->privat) {
+ if (key->u.a.privat) {
njs_vm_error(vm, "private key of \"%V\" cannot be exported "
"in \"raw\" format", njs_algorithm_string(key->alg));
return NJS_ERROR;
}
- ec = njs_pkey_get_ec_key(key->pkey);
+ ec = njs_pkey_get_ec_key(key->u.a.pkey);
group = EC_KEY_get0_group(ec);
point = EC_KEY_get0_public_key(ec);
njs_int_t ret;
njs_opaque_value_t ops, extractable;
- njs_assert(key->pkey != NULL);
+ njs_assert(key->u.a.pkey != NULL);
- switch (EVP_PKEY_id(key->pkey)) {
+ switch (EVP_PKEY_id(key->u.a.pkey)) {
case EVP_PKEY_RSA:
#if (OPENSSL_VERSION_NUMBER >= 0x10101001L)
case EVP_PKEY_RSA_PSS:
njs_opaque_value_t k, alg, ops, extractable, oct_s;
njs_webcrypto_alg_t type;
- njs_assert(key->raw.start != NULL);
+ njs_assert(key->u.s.raw.start != NULL);
- ret = njs_string_base64url(vm, njs_value_arg(&k), &key->raw);
+ ret = njs_string_base64url(vm, njs_value_arg(&k), &key->u.s.raw);
if (njs_slow_path(ret != NJS_OK)) {
return NJS_ERROR;
}
nm->length);
} else {
- switch (key->raw.length) {
+ switch (key->u.s.raw.length) {
case 16:
case 24:
case 32:
nm = &njs_webcrypto_alg_aes_name
- [type - NJS_ALGORITHM_AES_GCM][(key->raw.length - 16) / 8];
+ [type - NJS_ALGORITHM_AES_GCM][(key->u.s.raw.length - 16) / 8];
(void) njs_vm_value_string_set(vm, njs_value_arg(&alg), nm->start,
nm->length);
break;
break;
case NJS_KEY_FORMAT_PKCS8:
- if (!key->privat) {
+ if (!key->u.a.privat) {
njs_vm_error(vm, "public key of \"%V\" cannot be exported "
"as PKCS8", njs_algorithm_string(key->alg));
goto fail;
goto fail;
}
- njs_assert(key->pkey != NULL);
+ njs_assert(key->u.a.pkey != NULL);
- pkcs8 = EVP_PKEY2PKCS8(key->pkey);
+ pkcs8 = EVP_PKEY2PKCS8(key->u.a.pkey);
if (njs_slow_path(pkcs8 == NULL)) {
BIO_free(bio);
njs_webcrypto_error(vm, "EVP_PKEY2PKCS8() failed");
break;
case NJS_KEY_FORMAT_SPKI:
- if (key->privat) {
+ if (key->u.a.privat) {
njs_vm_error(vm, "private key of \"%V\" cannot be exported "
"as SPKI", njs_algorithm_string(key->alg));
goto fail;
goto fail;
}
- njs_assert(key->pkey != NULL);
+ njs_assert(key->u.a.pkey != NULL);
- if (!i2d_PUBKEY_bio(bio, key->pkey)) {
+ if (!i2d_PUBKEY_bio(bio, key->u.a.pkey)) {
BIO_free(bio);
njs_webcrypto_error(vm, "i2d_PUBKEY_bio() failed");
goto fail;
}
ret = njs_vm_value_array_buffer_set(vm, njs_value_arg(&value),
- key->raw.start, key->raw.length);
+ key->u.s.raw.start,
+ key->u.s.raw.length);
if (njs_slow_path(ret != NJS_OK)) {
goto fail;
}
goto fail;
}
- if (EVP_PKEY_keygen(ctx, &key->pkey) <= 0) {
+ if (EVP_PKEY_keygen(ctx, &key->u.a.pkey) <= 0) {
njs_webcrypto_error(vm, "EVP_PKEY_keygen() failed");
goto fail;
}
EVP_PKEY_CTX_free(ctx);
ctx = NULL;
- key->privat = 1;
+ key->u.a.privat = 1;
key->usage = (alg->type == NJS_ALGORITHM_RSA_OAEP)
? NJS_KEY_USAGE_DECRYPT
: NJS_KEY_USAGE_SIGN;
goto fail;
}
- if (njs_pkey_up_ref(key->pkey) <= 0) {
+ if (njs_pkey_up_ref(key->u.a.pkey) <= 0) {
njs_webcrypto_error(vm, "njs_pkey_up_ref() failed");
goto fail;
}
- keypub->pkey = key->pkey;
+ keypub->u.a.pkey = key->u.a.pkey;
keypub->hash = key->hash;
keypub->usage = (alg->type == NJS_ALGORITHM_RSA_OAEP)
? NJS_KEY_USAGE_ENCRYPT
goto fail;
}
- if (EVP_PKEY_keygen(ctx, &key->pkey) <= 0) {
+ if (EVP_PKEY_keygen(ctx, &key->u.a.pkey) <= 0) {
njs_webcrypto_error(vm, "EVP_PKEY_keygen() failed");
goto fail;
}
EVP_PKEY_CTX_free(ctx);
ctx = NULL;
- key->privat = 1;
+ key->u.a.privat = 1;
key->usage = NJS_KEY_USAGE_SIGN;
keypub = njs_webcrypto_key_alloc(vm, alg, usage, extractable);
goto fail;
}
- if (njs_pkey_up_ref(key->pkey) <= 0) {
+ if (njs_pkey_up_ref(key->u.a.pkey) <= 0) {
njs_webcrypto_error(vm, "njs_pkey_up_ref() failed");
goto fail;
}
- keypub->pkey = key->pkey;
- keypub->curve = key->curve;
+ keypub->u.a.pkey = key->u.a.pkey;
+ keypub->u.a.curve = key->u.a.curve;
keypub->usage = NJS_KEY_USAGE_VERIFY;
ret = njs_vm_external_create(vm, njs_value_arg(&priv),
goto fail;
}
- key->raw.length = EVP_MD_size(njs_algorithm_hash_digest(key->hash));
+ key->u.s.raw.length =
+ EVP_MD_size(njs_algorithm_hash_digest(key->hash));
} else {
val = njs_vm_object_prop(vm, aobject, &string_length, &value);
if (val != NULL) {
- key->raw.length = njs_value_number(val) / 8;
+ key->u.s.raw.length = njs_value_number(val) / 8;
- if (key->raw.length != 16
- && key->raw.length != 24
- && key->raw.length != 32)
+ if (key->u.s.raw.length != 16
+ && key->u.s.raw.length != 24
+ && key->u.s.raw.length != 32)
{
njs_vm_error(vm, "length for \"%V\" key should be one of "
"128, 192, 256", njs_algorithm_string(alg));
}
}
- key->raw.start = njs_mp_alloc(njs_vm_memory_pool(vm), key->raw.length);
- if (njs_slow_path(key->raw.start == NULL)) {
+ key->u.s.raw.start = njs_mp_alloc(njs_vm_memory_pool(vm),
+ key->u.s.raw.length);
+ if (njs_slow_path(key->u.s.raw.start == NULL)) {
njs_vm_memory_error(vm);
goto fail;
}
- if (RAND_bytes(key->raw.start, key->raw.length) <= 0) {
+ if (RAND_bytes(key->u.s.raw.start, key->u.s.raw.length) <= 0) {
njs_webcrypto_error(vm, "RAND_bytes() failed");
goto fail;
}
return NULL;
}
- key->privat = njs_value_is_string(njs_value_arg(&d));
+ key->u.a.privat = njs_value_is_string(njs_value_arg(&d));
val = njs_vm_object_prop(vm, jwk, &key_ops, &value);
if (val != NULL && !njs_value_is_undefined(val)){
goto fail;
}
- if (!key->privat) {
+ if (!key->u.a.privat) {
goto done;
}
EC_POINT *pub;
const EC_GROUP *group;
- ec = EC_KEY_new_by_curve_name(key->curve);
+ ec = EC_KEY_new_by_curve_name(key->u.a.curve);
if (njs_slow_path(ec == NULL)) {
njs_webcrypto_error(vm, "EC_KEY_new_by_curve_name() failed");
return NULL;
return NULL;
}
- key->privat = njs_value_is_string(njs_value_arg(&d));
+ key->u.a.privat = njs_value_is_string(njs_value_arg(&d));
val = njs_vm_object_prop(vm, jwk, &key_ops, &value);
if (val != NULL && !njs_value_is_undefined(val)) {
}
}
- if (curve != key->curve) {
+ if (curve != key->u.a.curve) {
njs_vm_error(vm, "JWK EC curve mismatch");
return NULL;
}
- ec = EC_KEY_new_by_curve_name(key->curve);
+ ec = EC_KEY_new_by_curve_name(key->u.a.curve);
if (njs_slow_path(ec == NULL)) {
njs_webcrypto_error(vm, "EC_KEY_new_by_curve_name() failed");
return NULL;
goto fail;
}
- if (key->privat) {
+ if (key->u.a.privat) {
d_bn = njs_import_base64url_bignum(vm, &d);
if (njs_slow_path(d_bn == NULL)) {
goto fail;
goto fail_pkey;
}
- if (key->privat) {
+ if (key->u.a.privat) {
if (!EC_KEY_set_private_key(ec, d_bn)) {
njs_webcrypto_error(vm, "EC_KEY_set_private_key() failed");
goto fail_pkey;
njs_value_string_get(val, &b64);
- (void) njs_decode_base64url_length(&b64, &key->raw.length);
+ (void) njs_decode_base64url_length(&b64, &key->u.s.raw.length);
- key->raw.start = njs_mp_alloc(njs_vm_memory_pool(vm), key->raw.length);
- if (njs_slow_path(key->raw.start == NULL)) {
+ key->u.s.raw.start = njs_mp_alloc(njs_vm_memory_pool(vm),
+ key->u.s.raw.length);
+ if (njs_slow_path(key->u.s.raw.start == NULL)) {
njs_vm_memory_error(vm);
return NJS_ERROR;
}
- njs_decode_base64url(&key->raw, &b64);
+ njs_decode_base64url(&key->u.s.raw, &b64);
size = 16;
done:
if (key->alg->type != NJS_ALGORITHM_HMAC) {
- if (key->raw.length != size) {
+ if (key->u.s.raw.length != size) {
njs_vm_error(vm, "key size and \"alg\" value \"%V\" mismatch",
&alg);
return NJS_ERROR;
/*
* set by njs_webcrypto_key_alloc():
*
- * key->pkey = NULL;
- * key->raw.length = 0;
- * key->raw.start = NULL;
- * key->curve = 0;
- * key->privat = 0;
+ * key->u.a.pkey = NULL;
+ * key->u.s.raw.length = 0;
+ * key->u.s.raw.start = NULL;
+ * key->u.a.curve = 0;
+ * key->u.a.privat = 0;
* key->hash = NJS_HASH_UNSET;
*/
PKCS8_PRIV_KEY_INFO_free(pkcs8);
BIO_free(bio);
- key->privat = 1;
+ key->u.a.privat = 1;
break;
}
} else if (njs_strstr_eq(&kty, &njs_str_value("EC"))) {
- ret = njs_algorithm_curve(vm, options, &key->curve);
+ ret = njs_algorithm_curve(vm, options, &key->u.a.curve);
if (njs_slow_path(ret == NJS_ERROR)) {
goto fail;
}
goto fail;
}
- if (key->privat) {
+ if (key->u.a.privat) {
mask = (alg->type == NJS_ALGORITHM_RSA_OAEP)
? ~(NJS_KEY_USAGE_DECRYPT | NJS_KEY_USAGE_UNWRAP_KEY)
: ~(NJS_KEY_USAGE_SIGN);
}
key->hash = hash;
- key->pkey = pkey;
+ key->u.a.pkey = pkey;
break;
case NJS_ALGORITHM_ECDSA:
case NJS_ALGORITHM_ECDH:
- ret = njs_algorithm_curve(vm, options, &key->curve);
+ ret = njs_algorithm_curve(vm, options, &key->u.a.curve);
if (njs_slow_path(ret == NJS_ERROR)) {
goto fail;
}
#endif
- if (njs_slow_path(key->curve != nid)) {
+ if (njs_slow_path(key->u.a.curve != nid)) {
njs_webcrypto_error(vm, "name curve mismatch");
goto fail;
}
- mask = key->privat ? ~NJS_KEY_USAGE_SIGN : ~NJS_KEY_USAGE_VERIFY;
+ mask = key->u.a.privat ? ~NJS_KEY_USAGE_SIGN : ~NJS_KEY_USAGE_VERIFY;
if (key->usage & mask) {
njs_vm_error(vm, "key usage mismatch for \"%V\" key",
goto fail;
}
- key->pkey = pkey;
+ key->u.a.pkey = pkey;
break;
goto fail;
}
- key->raw = key_data;
+ key->u.s.raw = key_data;
} else {
/* NJS_KEY_FORMAT_JWK. */
goto fail;
}
- key->raw = key_data;
+ key->u.s.raw = key_data;
}
break;
case NJS_ALGORITHM_PBKDF2:
case NJS_ALGORITHM_HKDF:
default:
- key->raw = key_data;
+ key->u.s.raw = key_data;
break;
}
outlen = m_len;
- p = HMAC(md, key->raw.start, key->raw.length, data.start, data.length,
- dst, &m_len);
+ p = HMAC(md, key->u.s.raw.start, key->u.s.raw.length, data.start,
+ data.length, dst, &m_len);
if (njs_slow_path(p == NULL || m_len != outlen)) {
njs_webcrypto_error(vm, "HMAC() failed");
goto fail;
}
- olen = EVP_PKEY_size(key->pkey);
+ olen = EVP_PKEY_size(key->u.a.pkey);
dst = njs_mp_zalloc(njs_vm_memory_pool(vm), olen);
if (njs_slow_path(dst == NULL)) {
njs_vm_memory_error(vm);
goto fail;
}
- pctx = EVP_PKEY_CTX_new(key->pkey, NULL);
+ pctx = EVP_PKEY_CTX_new(key->u.a.pkey, NULL);
if (njs_slow_path(pctx == NULL)) {
njs_webcrypto_error(vm, "EVP_PKEY_CTX_new() failed");
goto fail;
}
}
- ret = njs_set_rsa_padding(vm, options, key->pkey, pctx, alg->type);
+ ret = njs_set_rsa_padding(vm, options, key->u.a.pkey, pctx, alg->type);
if (njs_slow_path(ret != NJS_OK)) {
goto fail;
}
}
if (alg->type == NJS_ALGORITHM_ECDSA) {
- ret = njs_convert_der_to_p1363(vm, key->pkey, dst, outlen,
+ ret = njs_convert_der_to_p1363(vm, key->u.a.pkey, dst, outlen,
&dst, &outlen);
if (njs_slow_path(ret != NJS_OK)) {
goto fail;
} else {
if (alg->type == NJS_ALGORITHM_ECDSA) {
- ret = njs_convert_p1363_to_der(vm, key->pkey, sig.start,
+ ret = njs_convert_p1363_to_der(vm, key->u.a.pkey, sig.start,
sig.length, &sig.start,
&sig.length);
if (njs_slow_path(ret != NJS_OK)) {
{
njs_webcrypto_key_t *key = data;
- if (key->pkey != NULL) {
- EVP_PKEY_free(key->pkey);
+ if (!key->alg->raw) {
+ EVP_PKEY_free(key->u.a.pkey);
}
}