<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>