title: mbedtls_rsa_rsassa_pkcs1_v15_sign stack overflow
body: <p>I'm a hobbyist and this is my first dive into the world of C++ and embedded systems. I'm struggling a bit with <a href="https://tls.mbed.org/api/index.html" rel="nofollow noreferrer">mbedtls</a>.</p>
  <p>I'm trying to create a JWT to <a href="https://developers.google.com/identity/protocols/oauth2/service-account#httprest" rel="nofollow noreferrer">authenticate against google services</a>. This involves sha256 hashing some base64 encoded json objects (header.claim) and then RSASSA-PKCS1-V1_5-SIGN signing that.</p>
  <p>I seem to be ok up to the signing part. My understanding is I can parse the private key with mbedtls_pk_parse_key, and then use that mbedtls_pk_context with mbedtls_rsa_rsassa_pkcs1_v15_sign to sign the hash.</p>
  <p>My issue is two fold, I'm not certain I am using mbedtls_rsa_rsassa_pkcs1_v15_sign correctly as the resulting base64 encoded signature comes out as the following in the console. While the encoded json objects are readable.</p>
  <pre><code>encodedHeader: ewoJImFsZyI6CSJSUzI1NiIsCgkidHlwIjoJIkpXVCIKfQ==
  encodedSignature: ������������������������������������������������������...
  </code></pre>
  <p>Additionally right as this method returns, I get a stack overflow which I am not sure where it's coming from.</p>
  <pre><code>***ERROR*** A stack overflow in task main has been detected.
  
  
  Backtrace:0x40081c0a:0x3ffb82700x40085a4d:0x3ffb8290 0x40088716:0x3ffb82b0 0x4008748f:0x3ffb8330 0x40085b4c:0x3ffb8350 0x40085afe:0x00000000  |&lt;-CORRUPTED
  
  
  
  
  ELF file SHA256: 4307a925ab3c9b48
  </code></pre>
  <p>Here is my code, any help would be greatly appreciated.</p>
  <pre><code>// Encode Header
  unsigned char encodedHeader[92];
  size_t encodedHeaderSize;
  const unsigned char* headerRecast = reinterpret_cast&lt;const unsigned char *&gt;(cJSON_Print((const cJSON*) fHeader.toJSON()));
  mbedtls_base64_encode(encodedHeader, 92, &amp;encodedHeaderSize, headerRecast, strlen((const char *) headerRecast));
  ESP_LOGI(&quot;encodedHeader&quot;, &quot;%s&quot;, encodedHeader);
  
  // Encode Claim
  unsigned char encodedClaim[400];
  size_t encodedClaimSize;
  const unsigned char* claimRecast = reinterpret_cast&lt;const unsigned char *&gt;(cJSON_Print((const cJSON*) fClaim.toJSON()));
  mbedtls_base64_encode(encodedClaim, 400, &amp;encodedClaimSize, claimRecast, strlen((const char *) claimRecast));
  ESP_LOGI(&quot;encodedClaim&quot;, &quot;%s&quot;, encodedClaim);
  
  // Concat the header and claim together
  std::string headerStr((const char*) encodedHeader);
  std::string claimStr((const char*) encodedClaim);
  std::string auth = headerStr + &quot;.&quot; + claimStr;
  
  // Hash the header.claim
  const unsigned char* resultRecast = reinterpret_cast&lt;const unsigned char *&gt;(auth.c_str());
  mbedtls_sha256_context shaContext;
  unsigned char outHash[32];
  mbedtls_sha256_init(&amp;shaContext);
  mbedtls_sha256_starts(&amp;shaContext, 0);
  mbedtls_sha256_update(&amp;shaContext, resultRecast, strlen((const char *) resultRecast));
  mbedtls_sha256_finish(&amp;shaContext, outHash);
  mbedtls_sha256_free(&amp;shaContext);
  ESP_LOGI(&quot;outHash&quot;, &quot;%s&quot;, outHash);
  
  std::string shaStr;
  for (int i=0; i&lt;32; i++) { 
      char str[3];
      sprintf(str, &quot;%02x&quot;, (int)outHash[i]);
      shaStr += reinterpret_cast&lt;const char*&gt;(str);
  };
  
  // pkcs1_v15_sign sign the hash
  mbedtls_entropy_context entropy;
  mbedtls_ctr_drbg_context ctr_drbg;
  mbedtls_entropy_init( &amp;entropy );
  mbedtls_ctr_drbg_init( &amp;ctr_drbg );
  
  mbedtls_pk_context pkContext;
  mbedtls_pk_init(&amp;pkContext);
  mbedtls_pk_parse_key(
      &amp;pkContext,
      privateKey,
      2000,
      NULL,
      0);
  auto rsa = mbedtls_pk_rsa(pkContext);
  unsigned char signature[2000];
  int res = mbedtls_rsa_rsassa_pkcs1_v15_sign(rsa,
                                      mbedtls_ctr_drbg_random, &amp;ctr_drbg,
                                      MBEDTLS_RSA_PRIVATE,
                                      MBEDTLS_MD_SHA256,
                                      32, reinterpret_cast&lt;const unsigned char*&gt;(shaStr.c_str()),
                                      signature);
  
  // Release Resources
  mbedtls_rsa_free( rsa );
  mbedtls_ctr_drbg_free( &amp;ctr_drbg );
  mbedtls_entropy_free( &amp;entropy );
  
  // Encode Signature
  unsigned char encodedSignature[2000];
  size_t encodedSignatureSize;
  mbedtls_base64_encode(encodedSignature, 2000, &amp;encodedSignatureSize, (const unsigned char*) signature, strlen((const char *) signature));
  ESP_LOGI(&quot;encodedSignature&quot;, &quot;%s&quot;, encodedSignature);
  
  // Concat encoded hash.signature
  std::string sig((const char*) encodedSignature);
  std::string token = shaStr + &quot;.&quot; + sig;
  return token.c_str();
  </code></pre>
  <p>If it helps to understand my goal, here is a proof of concept I made in python</p>
  <pre><code>import requests
  from Crypto.Signature import PKCS1_v1_5
  from Crypto.PublicKey import RSA
  from Crypto.Hash import SHA256
  from base64 import urlsafe_b64encode, urlsafe_b64decode
  import json
  import time
  
  
  now = int(time.time())
  header = {&quot;alg&quot;: &quot;RS256&quot;, &quot;typ&quot;: &quot;JWT&quot;}
  claim = {
    &quot;iss&quot;: &quot;something&quot;,
    &quot;scope&quot;: &quot;something&quot;,
    &quot;aud&quot;: &quot;https://oauth2.googleapis.com/token&quot;,
    &quot;exp&quot;: now + 3600,
    &quot;iat&quot;: now
  }
  
  key = &quot;{}.{}&quot;.format(urlsafe_b64encode(json.dumps(header).encode()).decode(), urlsafe_b64encode(json.dumps(claim).encode()).decode())
  
  with open('key.json', 'r') as f:
      creds = json.load(f)
  
  keyPub = RSA.importKey(creds.get('private_key'))
  h = SHA256.new(key.encode())
  signer = PKCS1_v1_5.new(keyPub)
  signature = signer.sign(h)
  
  key = &quot;{}.{}&quot;.format(key, urlsafe_b64encode(signature).decode())
  print(key)
  </code></pre>