Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@ All notable changes to this project will be documented in this file. Dates are d

Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).

#### [2.2.0](https://github.com/rdkcentral/javascript-templates/compare/2.1.0...2.2.0)

- RDKB-65466 : sso validation token [`#19`](https://github.com/rdkcentral/javascript-templates/pull/19)
- Merge tag '2.1.0' into develop [`6246ada`](https://github.com/rdkcentral/javascript-templates/commit/6246adaaa950bded6b962e748c7f4058285f0a6f)

#### [2.1.0](https://github.com/rdkcentral/javascript-templates/compare/2.0.0...2.1.0)

> 7 May 2026

- RDKB-63696 CMXB7-6329 CPU & Load average spike and jst crash during stability test [`#15`](https://github.com/rdkcentral/javascript-templates/pull/15)
- Add changelog for release 2.1.0 [`32e56da`](https://github.com/rdkcentral/javascript-templates/commit/32e56da5db64fa93f399f27867a83cccdcabf1ac)
- Merge tag '2.0.0' into develop [`591bc95`](https://github.com/rdkcentral/javascript-templates/commit/591bc9532ad335d4ed3a3e7b962854f8c63263e8)

### [2.0.0](https://github.com/rdkcentral/javascript-templates/compare/1.0.1...2.0.0)
Expand Down
127 changes: 115 additions & 12 deletions source/jst_functions.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
If not stated otherwise in this file or this component's Licenses.txt file the

Check failure on line 2 in source/jst_functions.c

View workflow job for this annotation

GitHub Actions / call-fossid-workflow / Fossid Annotate PR

FossID Detected License Issue

Snippet with 'Apache-2.0' file license found (580 lines) Location: source/jst_functions.c (link unavailable) Component: rdk/components/generic/jst/rdk/components/generic/jst@rdk-dev-2101 Download: https://code.rdkcentral.com/r/plugins/gitiles/rdk/components/generic/jst/+archive/rdk-dev-2101.tar.gz
following copyright and licenses apply:

Copyright 2018 RDK Management
Expand Down Expand Up @@ -494,13 +494,81 @@
}
}

/* Helper function: Decode base64url string to binary signature */
static unsigned char* base64url_decode_signature(const char* sig_base64url, size_t input_len, size_t* output_len)
{
char* b64_input = NULL;
unsigned char* sig_bytes = NULL;
BIO *bio, *b64;
size_t max_len;

if (!sig_base64url || input_len == 0) {
CosaPhpExtLog("base64url_decode_signature: invalid input\n");
return NULL;
}

/* Allocate space for conversion (+4 for potential padding) */
b64_input = malloc(input_len + 4);
if (!b64_input) {
CosaPhpExtLog("base64url_decode_signature: malloc failed for b64_input\n");
return NULL;
}

/* Copy and convert URL-safe chars to standard base64 */
memcpy(b64_input, sig_base64url, input_len);
b64_input[input_len] = '\0';

for (size_t i = 0; i < input_len; i++) {
if (b64_input[i] == '-') b64_input[i] = '+';
else if (b64_input[i] == '_') b64_input[i] = '/';
}

/* Add padding if needed */
size_t mod = input_len % 4;
if (mod == 2) {
strcat(b64_input, "==");
} else if (mod == 3) {
strcat(b64_input, "=");
}

/* Allocate buffer for decoded data */
max_len = (input_len * 3) / 4 + 1;
sig_bytes = malloc(max_len);
if (!sig_bytes) {
free(b64_input);
CosaPhpExtLog("base64url_decode_signature: malloc failed for sig_bytes\n");
return NULL;
}

/* Decode using OpenSSL BIO */
bio = BIO_new_mem_buf(b64_input, -1);
b64 = BIO_new(BIO_f_base64());
bio = BIO_push(b64, bio);
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);

*output_len = BIO_read(bio, sig_bytes, max_len);
BIO_free_all(bio);
free(b64_input);

if (*output_len <= 0) {
free(sig_bytes);
CosaPhpExtLog("base64url_decode_signature: BIO_read failed\n");
return NULL;
}

CosaPhpExtLog("base64url_decode_signature: decoded %zu bytes from %zu byte input\n", *output_len, input_len);
return sig_bytes;
}

static duk_ret_t do_openssl_verify_with_cert(duk_context *ctx)
{
char* filepath;
char* token;
char* sig2verify;
char* sig_base64url; /* Base64url-encoded signature string */
char* alg;

size_t sig_base64url_len = 0;
unsigned char* sig_bytes = NULL; /* Decoded binary signature */
size_t sig_len = 0;
BIO* bio = NULL;
X509* cert = NULL;
EVP_PKEY * key = NULL;
Expand All @@ -511,23 +579,54 @@

/* note that SHA256 is currently the only supported digest by this function
* add more as necessary using EVP_add_digest() or OpenSSL_add_all_digests() */
if (!parse_parameter(__FUNCTION__, ctx, "ssss", &filepath, &token, &sig2verify, &alg))
{
CosaPhpExtLog("openssl_verify_with_cert: failed to parse parameters\n");

/* Get all parameters directly from Duktape stack */
if (duk_get_top(ctx) < 4) {
CosaPhpExtLog("openssl_verify_with_cert: insufficient parameters (need 4, got %d)\n", duk_get_top(ctx));
RETURN_FALSE;
}

filepath = duk_get_string(ctx, 0);
token = duk_get_string(ctx, 1);
sig_base64url = duk_get_lstring(ctx, 2, &sig_base64url_len); /* Get base64url string */
alg = duk_get_string(ctx, 3);

if (!filepath || !token || !sig_base64url || !alg) {
CosaPhpExtLog("openssl_verify_with_cert: NULL parameter detected\n");
RETURN_FALSE;
}

if (sig_base64url_len == 0) {
CosaPhpExtLog("openssl_verify_with_cert: signature length is 0 - invalid signature data\n");
RETURN_FALSE;
}

CosaPhpExtLog("openssl_verify_with_cert: Received base64url signature length=%zu, alg=%s\n", sig_base64url_len, alg);

/* === DECODE BASE64URL SIGNATURE === */
sig_bytes = base64url_decode_signature(sig_base64url, sig_base64url_len, &sig_len);
if (!sig_bytes) {
CosaPhpExtLog("openssl_verify_with_cert: Failed to decode base64url signature\n");
RETURN_FALSE;
}

CosaPhpExtLog("openssl_verify_with_cert: Decoded signature to %zu bytes (expected ~256 for RS256)\n", sig_len);

/* === NOW PROCEED WITH SIGNATURE VERIFICATION === */

//open certificate file
if(memcmp(filepath, "file://", sizeof("file://")-1) != 0)
{
CosaPhpExtLog("openssl_verify_with_cert: file %s doesn't begin with 'file://'\n", filepath);
free(sig_bytes);
RETURN_FALSE;
}
filepath += sizeof("file://") - 1;
bio = BIO_new_file(filepath, "rb") ;
if(!bio)
{
CosaPhpExtLog("openssl_verify_with_cert: failed open file %s\n", filepath);
free(sig_bytes);
RETURN_FALSE;
}

Expand All @@ -548,20 +647,22 @@
}

BIO_free(bio);

bio = NULL;
if(!key)
{
CosaPhpExtLog("openssl_verify_with_cert: failed read public key from %s\n", filepath);
free(sig_bytes);
RETURN_FALSE;
}

EVP_add_digest(EVP_sha256());

mdtype = EVP_get_digestbyname(alg);
mdtype = EVP_sha256();
if(!mdtype)
{
CosaPhpExtLog("openssl_verify_with_cert: EVP_get_digestbyname failed for %s\n", alg);
EVP_PKEY_free(key);
free(sig_bytes);
RETURN_FALSE;
}

Expand All @@ -570,22 +671,23 @@
{
CosaPhpExtLog("openssl_verify_with_cert: EVP_MD_CTX_create failed\n");
EVP_PKEY_free(key);
free(sig_bytes);
RETURN_FALSE;
}

if(EVP_VerifyInit (md_ctx, mdtype))
{
if(EVP_VerifyUpdate (md_ctx, token, strlen(token)))
{
err = EVP_VerifyFinal(md_ctx, (unsigned char *)sig2verify, (unsigned int)strlen(sig2verify), key);
if(err < 0)
err = EVP_VerifyFinal(md_ctx, sig_bytes, (unsigned int)sig_len, key);
if(err == 1)
{
CosaPhpExtLog("openssl_verify_with_cert: EVP_VerifyFinal failed error:%d\n", err);
ok = 1;
CosaPhpExtLog("openssl_verify_with_cert: EVP_VerifyFinal success\n");
}
else
{
ok = 1;
CosaPhpExtLog("openssl_verify_with_cert: EVP_VerifyFinal success\n");
CosaPhpExtLog("openssl_verify_with_cert: EVP_VerifyFinal failed error:%d\n", err);
}
}
else
Expand All @@ -599,6 +701,7 @@
}
EVP_MD_CTX_destroy(md_ctx);
EVP_PKEY_free(key);
free(sig_bytes); /* Clean up decoded signature */
if(ok)
{
RETURN_TRUE;
Expand Down
Loading