<p>Joshua Colp <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/15848">View Change</a></p><div style="white-space:pre-wrap">Approvals:
George Joseph: Looks good to me, approved
Joshua Colp: Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">STIR/SHAKEN: Switch to base64 URL encoding.<br><br>STIR/SHAKEN encodes using base64 URL format. Currently, we just use<br>base64. New functions have been added that convert to and from base64<br>encoding.<br><br>The origid field should also be an UUID. This means there's no reason to<br>have it as an option in stir_shaken.conf, as we can simply generate one<br>when creating the Identity header.<br><br>https://wiki.asterisk.org/wiki/display/AST/OpenSIPit+2021<br><br>Change-Id: Icf094a2a54e87db91d6b12244c9f5ba4fc2e0b8c<br>---<br>M configs/samples/stir_shaken.conf.sample<br>A doc/UPGRADE-staging/stir_shaken_origid.txt<br>M include/asterisk/utils.h<br>M main/utils.c<br>M res/res_pjsip_stir_shaken.c<br>M res/res_stir_shaken.c<br>M res/res_stir_shaken/certificate.c<br>M res/res_stir_shaken/certificate.h<br>8 files changed, 214 insertions(+), 46 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/configs/samples/stir_shaken.conf.sample b/configs/samples/stir_shaken.conf.sample</span><br><span>index 1bd2606..c39bc97 100644</span><br><span>--- a/configs/samples/stir_shaken.conf.sample</span><br><span>+++ b/configs/samples/stir_shaken.conf.sample</span><br><span>@@ -83,6 +83,3 @@</span><br><span> ;</span><br><span> ; Must have an attestation of A, B, or C</span><br><span> ;attestation=C</span><br><span style="color: hsl(0, 100%, 40%);">-;</span><br><span style="color: hsl(0, 100%, 40%);">-; The origination identifier for the certificate</span><br><span style="color: hsl(0, 100%, 40%);">-;origid=MyAsterisk</span><br><span>diff --git a/doc/UPGRADE-staging/stir_shaken_origid.txt b/doc/UPGRADE-staging/stir_shaken_origid.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..f0b8977</span><br><span>--- /dev/null</span><br><span>+++ b/doc/UPGRADE-staging/stir_shaken_origid.txt</span><br><span>@@ -0,0 +1,8 @@</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: STIR/SHAKEN</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+STIR/SHAKEN originally needed an origid to be specified in</span><br><span style="color: hsl(120, 100%, 40%);">+stir_shaken.conf under the certificate config object in</span><br><span style="color: hsl(120, 100%, 40%);">+order to work. Now, one is automatically created by</span><br><span style="color: hsl(120, 100%, 40%);">+generating a UUID, as recommended by RFC8588. Any origid</span><br><span style="color: hsl(120, 100%, 40%);">+you have in your stir_shaken.conf will need to be removed</span><br><span style="color: hsl(120, 100%, 40%);">+for the module to read in certificates.</span><br><span>diff --git a/include/asterisk/utils.h b/include/asterisk/utils.h</span><br><span>index 0ee11ee..08120bf 100644</span><br><span>--- a/include/asterisk/utils.h</span><br><span>+++ b/include/asterisk/utils.h</span><br><span>@@ -276,6 +276,66 @@</span><br><span> */</span><br><span> char *ast_base64decode_string(const char *src);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Decode data from base64 URL</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param dst The destination buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param src The source buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param max The maximum number of bytes to write into the destination</span><br><span style="color: hsl(120, 100%, 40%);">+ * buffer. Note that this function will not ensure that the</span><br><span style="color: hsl(120, 100%, 40%);">+ * destination buffer is NULL terminated. So, in general,</span><br><span style="color: hsl(120, 100%, 40%);">+ * this parameter should be sizeof(dst) - 1</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_base64url_decode(unsigned char *dst, const char *src, int max);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Same as ast_base64encode_full but for base64 URL</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param dst The destination buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param src The source buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param srclen The number of bytes present in the source buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param max The maximum number of bytes to write into the destination</span><br><span style="color: hsl(120, 100%, 40%);">+ * buffer, *including* the terminating NULL character.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param linebreaks Set to 1 if there should be linebreaks inserted</span><br><span style="color: hsl(120, 100%, 40%);">+ * in the result</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_base64url_encode_full(char *dst, const unsigned char *src, int srclen, int max, int linebreaks);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Encode data in base64 URL</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param dst The destination buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param src The source data to be encoded</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param srclen The number of bytes present in the source buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param max The maximum number of bytes to write into the destination</span><br><span style="color: hsl(120, 100%, 40%);">+ * buffer, including the terminating NULL character</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_base64url_encode(char *dst, const unsigned char *src, int srclen, int max);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Decode string from base64 URL</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \note The returned string will need to be freed later</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param src The source buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval NULL on failure</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval Decoded string on success</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+char *ast_base64url_decode_string(const char *src);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Encode string in base64 URL</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \note The returned string will need to be freed later</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param src The source data to be encoded</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval NULL on failure</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval Encoded string on success</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+char *ast_base64url_encode_string(const char *src);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #define AST_URI_ALPHANUM (1 << 0)</span><br><span> #define AST_URI_MARK (1 << 1)</span><br><span> #define AST_URI_UNRESERVED (AST_URI_ALPHANUM | AST_URI_MARK)</span><br><span>diff --git a/main/utils.c b/main/utils.c</span><br><span>index 827ee2e..c6e71d9 100644</span><br><span>--- a/main/utils.c</span><br><span>+++ b/main/utils.c</span><br><span>@@ -70,8 +70,15 @@</span><br><span> #define AST_API_MODULE</span><br><span> #include "asterisk/alertpipe.h"</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* These arrays are global static variables because they are only modified</span><br><span style="color: hsl(120, 100%, 40%);">+ * once - in base64_init. The only purpose they have is to serve as a dictionary</span><br><span style="color: hsl(120, 100%, 40%);">+ * for encoding and decoding base64 and base64 URL, so there's no harm in</span><br><span style="color: hsl(120, 100%, 40%);">+ * accessing these arrays in multiple threads.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span> static char base64[64];</span><br><span style="color: hsl(120, 100%, 40%);">+static char base64url[64];</span><br><span> static char b2a[256];</span><br><span style="color: hsl(120, 100%, 40%);">+static char b2a_url[256];</span><br><span> </span><br><span> AST_THREADSTORAGE(inet_ntoa_buf);</span><br><span> </span><br><span>@@ -417,28 +424,150 @@</span><br><span> return encoded_string;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+int ast_base64url_decode(unsigned char *dst, const char *src, int max)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int cnt = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int byte = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int bits = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ while (*src && (cnt < max)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ byte <<= 6;</span><br><span style="color: hsl(120, 100%, 40%);">+ byte |= (b2a_url[(int)(*src)]) & 0x3f;</span><br><span style="color: hsl(120, 100%, 40%);">+ bits += 6;</span><br><span style="color: hsl(120, 100%, 40%);">+ src++;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bits >= 8) {</span><br><span style="color: hsl(120, 100%, 40%);">+ bits -= 8;</span><br><span style="color: hsl(120, 100%, 40%);">+ *dst = (byte >> bits) & 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+ dst++;</span><br><span style="color: hsl(120, 100%, 40%);">+ cnt++;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return cnt;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+char *ast_base64url_decode_string(const char *src)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t decoded_len;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned char *decoded_string;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(src)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ decoded_len = strlen(src) * 3 / 4;</span><br><span style="color: hsl(120, 100%, 40%);">+ decoded_string = ast_malloc(decoded_len + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!decoded_string) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_base64url_decode(decoded_string, src, decoded_len);</span><br><span style="color: hsl(120, 100%, 40%);">+ decoded_string[decoded_len] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return (char *)decoded_string;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_base64url_encode_full(char *dst, const unsigned char *src, int srclen, int max, int linebreaks)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int cnt = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ int col = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int byte = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ int bits = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ int cntin = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ max--;</span><br><span style="color: hsl(120, 100%, 40%);">+ while ((cntin < srclen) && (cnt < max)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ byte <<= 8;</span><br><span style="color: hsl(120, 100%, 40%);">+ byte |= *(src++);</span><br><span style="color: hsl(120, 100%, 40%);">+ bits += 8;</span><br><span style="color: hsl(120, 100%, 40%);">+ cntin++;</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((bits == 24) && (cnt + 4 <= max)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ *dst++ = base64url[(byte >> 18) & 0x3f];</span><br><span style="color: hsl(120, 100%, 40%);">+ *dst++ = base64url[(byte >> 12) & 0x3f];</span><br><span style="color: hsl(120, 100%, 40%);">+ *dst++ = base64url[(byte >> 6) & 0x3f];</span><br><span style="color: hsl(120, 100%, 40%);">+ *dst++ = base64url[(byte) & 0x3f];</span><br><span style="color: hsl(120, 100%, 40%);">+ cnt += 4;</span><br><span style="color: hsl(120, 100%, 40%);">+ col += 4;</span><br><span style="color: hsl(120, 100%, 40%);">+ bits = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ byte = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (linebreaks && (cnt < max) && (col == 64)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ *dst++ = '\n';</span><br><span style="color: hsl(120, 100%, 40%);">+ cnt++;</span><br><span style="color: hsl(120, 100%, 40%);">+ col = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bits && (cnt + 4 <= max)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ byte <<= 24 - bits;</span><br><span style="color: hsl(120, 100%, 40%);">+ *dst++ = base64url[(byte >> 18) & 0x3f];</span><br><span style="color: hsl(120, 100%, 40%);">+ *dst++ = base64url[(byte >> 12) & 0x3f];</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bits == 16) {</span><br><span style="color: hsl(120, 100%, 40%);">+ *dst++ = base64url[(byte >> 6) & 0x3f];</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ cnt += 4;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (linebreaks && (cnt < max)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ *dst++ = '\n';</span><br><span style="color: hsl(120, 100%, 40%);">+ cnt++;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ *dst = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+ return cnt;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_base64url_encode(char *dst, const unsigned char *src, int srclen, int max)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return ast_base64url_encode_full(dst, src, srclen, max, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+char *ast_base64url_encode_string(const char *src)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t encoded_len;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *encoded_string;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(src)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ encoded_len = ((strlen(src) * 4 / 3 + 3) & ~3) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ encoded_string = ast_malloc(encoded_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_base64url_encode(encoded_string, (const unsigned char *)src, strlen(src), encoded_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return encoded_string;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static void base64_init(void)</span><br><span> {</span><br><span> int x;</span><br><span> memset(b2a, -1, sizeof(b2a));</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(b2a_url, -1, sizeof(b2a_url));</span><br><span> /* Initialize base-64 Conversion table */</span><br><span> for (x = 0; x < 26; x++) {</span><br><span> /* A-Z */</span><br><span> base64[x] = 'A' + x;</span><br><span style="color: hsl(120, 100%, 40%);">+ base64url[x] = 'A' + x;</span><br><span> b2a['A' + x] = x;</span><br><span style="color: hsl(120, 100%, 40%);">+ b2a_url['A' + x] = x;</span><br><span> /* a-z */</span><br><span> base64[x + 26] = 'a' + x;</span><br><span style="color: hsl(120, 100%, 40%);">+ base64url[x + 26] = 'a' + x;</span><br><span> b2a['a' + x] = x + 26;</span><br><span style="color: hsl(120, 100%, 40%);">+ b2a_url['a' + x] = x + 26;</span><br><span> /* 0-9 */</span><br><span> if (x < 10) {</span><br><span> base64[x + 52] = '0' + x;</span><br><span style="color: hsl(120, 100%, 40%);">+ base64url[x + 52] = '0' + x;</span><br><span> b2a['0' + x] = x + 52;</span><br><span style="color: hsl(120, 100%, 40%);">+ b2a_url['0' + x] = x + 52;</span><br><span> }</span><br><span> }</span><br><span> base64[62] = '+';</span><br><span> base64[63] = '/';</span><br><span style="color: hsl(120, 100%, 40%);">+ base64url[62] = '-';</span><br><span style="color: hsl(120, 100%, 40%);">+ base64url[63] = '_';</span><br><span> b2a[(int)'+'] = 62;</span><br><span> b2a[(int)'/'] = 63;</span><br><span style="color: hsl(120, 100%, 40%);">+ b2a_url[(int)'-'] = 62;</span><br><span style="color: hsl(120, 100%, 40%);">+ b2a_url[(int)'_'] = 63;</span><br><span> }</span><br><span> </span><br><span> const struct ast_flags ast_uri_http = {AST_URI_UNRESERVED};</span><br><span>diff --git a/res/res_pjsip_stir_shaken.c b/res/res_pjsip_stir_shaken.c</span><br><span>index 62e3928..5a38073 100644</span><br><span>--- a/res/res_pjsip_stir_shaken.c</span><br><span>+++ b/res/res_pjsip_stir_shaken.c</span><br><span>@@ -149,14 +149,14 @@</span><br><span> }</span><br><span> </span><br><span> encoded_val = strtok_r(identity_hdr_val, ".", &identity_hdr_val);</span><br><span style="color: hsl(0, 100%, 40%);">- header = ast_base64decode_string(encoded_val);</span><br><span style="color: hsl(120, 100%, 40%);">+ header = ast_base64url_decode_string(encoded_val);</span><br><span> if (ast_strlen_zero(header)) {</span><br><span> ast_stir_shaken_add_verification(chan, caller_id, "", AST_STIR_SHAKEN_VERIFY_SIGNATURE_FAILED);</span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span> encoded_val = strtok_r(identity_hdr_val, ".", &identity_hdr_val);</span><br><span style="color: hsl(0, 100%, 40%);">- payload = ast_base64decode_string(encoded_val);</span><br><span style="color: hsl(120, 100%, 40%);">+ payload = ast_base64url_decode_string(encoded_val);</span><br><span> if (ast_strlen_zero(payload)) {</span><br><span> ast_stir_shaken_add_verification(chan, caller_id, "", AST_STIR_SHAKEN_VERIFY_SIGNATURE_FAILED);</span><br><span> return 0;</span><br><span>@@ -244,7 +244,7 @@</span><br><span> </span><br><span> header = ast_json_object_get(json, "header");</span><br><span> dumped_string = ast_json_dump_string(header);</span><br><span style="color: hsl(0, 100%, 40%);">- encoded_header = ast_base64encode_string(dumped_string);</span><br><span style="color: hsl(120, 100%, 40%);">+ encoded_header = ast_base64url_encode_string(dumped_string);</span><br><span> ast_json_free(dumped_string);</span><br><span> if (!encoded_header) {</span><br><span> ast_log(LOG_ERROR, "Failed to encode STIR/SHAKEN header\n");</span><br><span>@@ -253,7 +253,7 @@</span><br><span> </span><br><span> payload = ast_json_object_get(json, "payload");</span><br><span> dumped_string = ast_json_dump_string(payload);</span><br><span style="color: hsl(0, 100%, 40%);">- encoded_payload = ast_base64encode_string(dumped_string);</span><br><span style="color: hsl(120, 100%, 40%);">+ encoded_payload = ast_base64url_encode_string(dumped_string);</span><br><span> ast_json_free(dumped_string);</span><br><span> if (!encoded_payload) {</span><br><span> ast_log(LOG_ERROR, "Failed to encode STIR/SHAKEN payload\n");</span><br><span>diff --git a/res/res_stir_shaken.c b/res/res_stir_shaken.c</span><br><span>index f8eb97f..dbc2de0 100644</span><br><span>--- a/res/res_stir_shaken.c</span><br><span>+++ b/res/res_stir_shaken.c</span><br><span>@@ -104,9 +104,6 @@</span><br><span> <configOption name="attestation"></span><br><span> <synopsis>Attestation level</synopsis></span><br><span> </configOption></span><br><span style="color: hsl(0, 100%, 40%);">- <configOption name="origid" default=""></span><br><span style="color: hsl(0, 100%, 40%);">- <synopsis>The origination ID</synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- </configOption></span><br><span> <configOption name="caller_id_number" default=""></span><br><span> <synopsis>The caller ID number to match on.</synopsis></span><br><span> </configOption></span><br><span>@@ -503,7 +500,7 @@</span><br><span> EVP_MD_CTX *mdctx = NULL;</span><br><span> int ret = 0;</span><br><span> unsigned char *decoded_signature;</span><br><span style="color: hsl(0, 100%, 40%);">- size_t signature_length, decoded_signature_length, padding = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t signature_length, decoded_signature_length;</span><br><span> </span><br><span> mdctx = EVP_MD_CTX_create();</span><br><span> if (!mdctx) {</span><br><span>@@ -525,19 +522,12 @@</span><br><span> return -1;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /* We need to decode the signature from base64 to bytes. Make sure we have</span><br><span style="color: hsl(120, 100%, 40%);">+ /* We need to decode the signature from base64 URL to bytes. Make sure we have</span><br><span> * at least enough characters for this check */</span><br><span> signature_length = strlen(signature);</span><br><span style="color: hsl(0, 100%, 40%);">- if (signature_length > 2 && signature[signature_length - 1] == '=') {</span><br><span style="color: hsl(0, 100%, 40%);">- padding++;</span><br><span style="color: hsl(0, 100%, 40%);">- if (signature[signature_length - 2] == '=') {</span><br><span style="color: hsl(0, 100%, 40%);">- padding++;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- decoded_signature_length = (signature_length / 4 * 3) - padding;</span><br><span style="color: hsl(120, 100%, 40%);">+ decoded_signature_length = (signature_length * 3 / 4);</span><br><span> decoded_signature = ast_calloc(1, decoded_signature_length);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_base64decode(decoded_signature, signature, decoded_signature_length);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_base64url_decode(decoded_signature, signature, decoded_signature_length);</span><br><span> </span><br><span> ret = EVP_DigestVerifyFinal(mdctx, decoded_signature, decoded_signature_length);</span><br><span> if (ret != 1) {</span><br><span>@@ -944,7 +934,7 @@</span><br><span> goto cleanup;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /* There are 6 bits to 1 base64 digit, so in order to get the size of the base64 encoded</span><br><span style="color: hsl(120, 100%, 40%);">+ /* There are 6 bits to 1 base64 URL digit, so in order to get the size of the base64 encoded</span><br><span> * signature, we need to multiply by the number of bits in a byte and divide by 6. Since</span><br><span> * there's rounding when doing base64 conversions, add 3 bytes, just in case, and account</span><br><span> * for padding. Add another byte for the NULL-terminator.</span><br><span>@@ -956,7 +946,7 @@</span><br><span> goto cleanup;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ast_base64encode((char *)encoded_signature, signature, signature_length, encoded_length);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_base64url_encode((char *)encoded_signature, signature, signature_length, encoded_length);</span><br><span> </span><br><span> cleanup:</span><br><span> if (mdctx) {</span><br><span>@@ -1013,20 +1003,22 @@</span><br><span> * \brief Adds the 'origid' field to the JWT.</span><br><span> *</span><br><span> * \param json The JWT</span><br><span style="color: hsl(0, 100%, 40%);">- * \param origid The value to set origid to</span><br><span> *</span><br><span> * \retval 0 on success</span><br><span> * \retval -1 on failure</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">-static int stir_shaken_add_origid(struct ast_json *json, const char *origid)</span><br><span style="color: hsl(120, 100%, 40%);">+static int stir_shaken_add_origid(struct ast_json *json)</span><br><span> {</span><br><span> struct ast_json *value;</span><br><span style="color: hsl(120, 100%, 40%);">+ char uuid_str[AST_UUID_STR_LEN];</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- value = ast_json_string_create(origid);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!origid) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_uuid_generate_str(uuid_str, sizeof(uuid_str));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strlen(uuid_str) != (AST_UUID_STR_LEN - 1)) {</span><br><span> return -1;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ value = ast_json_string_create(uuid_str);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> return ast_json_object_set(ast_json_object_get(json, "payload"), "origid", value);</span><br><span> }</span><br><span> </span><br><span>@@ -1097,7 +1089,7 @@</span><br><span> goto cleanup;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (stir_shaken_add_origid(json, stir_shaken_certificate_get_origid(cert))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (stir_shaken_add_origid(json)) {</span><br><span> ast_log(LOG_ERROR, "Failed to add 'origid' to payload\n");</span><br><span> goto cleanup;</span><br><span> }</span><br><span>diff --git a/res/res_stir_shaken/certificate.c b/res/res_stir_shaken/certificate.c</span><br><span>index f4103f9..df4f38b 100644</span><br><span>--- a/res/res_stir_shaken/certificate.c</span><br><span>+++ b/res/res_stir_shaken/certificate.c</span><br><span>@@ -40,8 +40,6 @@</span><br><span> AST_STRING_FIELD(caller_id_number);</span><br><span> /*! The attestation level for this certificate */</span><br><span> AST_STRING_FIELD(attestation);</span><br><span style="color: hsl(0, 100%, 40%);">- /*! The origination ID for this certificate */</span><br><span style="color: hsl(0, 100%, 40%);">- AST_STRING_FIELD(origid);</span><br><span> );</span><br><span> /*! The private key for the certificate */</span><br><span> EVP_PKEY *private_key;</span><br><span>@@ -105,11 +103,6 @@</span><br><span> return cert ? cert->attestation : NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-const char *stir_shaken_certificate_get_origid(struct stir_shaken_certificate *cert)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return cert ? cert->origid : NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> EVP_PKEY *stir_shaken_certificate_get_private_key(struct stir_shaken_certificate *cert)</span><br><span> {</span><br><span> return cert ? cert->private_key : NULL;</span><br><span>@@ -378,7 +371,6 @@</span><br><span> on_load_public_cert_url, public_cert_url_to_str, NULL, 0, 0);</span><br><span> ast_sorcery_object_field_register_custom(sorcery, CONFIG_TYPE, "attestation", "",</span><br><span> on_load_attestation, attestation_to_str, NULL, 0, 0);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_sorcery_object_field_register(sorcery, CONFIG_TYPE, "origid", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct stir_shaken_certificate, origid));</span><br><span> ast_sorcery_object_field_register(sorcery, CONFIG_TYPE, "caller_id_number", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct stir_shaken_certificate, caller_id_number));</span><br><span> </span><br><span> ast_cli_register_multiple(stir_shaken_certificate_cli,</span><br><span>diff --git a/res/res_stir_shaken/certificate.h b/res/res_stir_shaken/certificate.h</span><br><span>index 9574d46..c95cba5 100644</span><br><span>--- a/res/res_stir_shaken/certificate.h</span><br><span>+++ b/res/res_stir_shaken/certificate.h</span><br><span>@@ -55,16 +55,6 @@</span><br><span> const char *stir_shaken_certificate_get_attestation(struct stir_shaken_certificate *cert);</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Get the origination ID associated with a certificate</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \param cert The certificate</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval NULL on failure</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval The origid on success</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-const char *stir_shaken_certificate_get_origid(struct stir_shaken_certificate *cert);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span> * \brief Get the private key associated with a certificate</span><br><span> *</span><br><span> * \param cert The certificate to get the private key from</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/15848">change 15848</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/15848"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 16 </div>
<div style="display:none"> Gerrit-Change-Id: Icf094a2a54e87db91d6b12244c9f5ba4fc2e0b8c </div>
<div style="display:none"> Gerrit-Change-Number: 15848 </div>
<div style="display:none"> Gerrit-PatchSet: 5 </div>
<div style="display:none"> Gerrit-Owner: Benjamin Keith Ford <bford@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@sangoma.com> </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>