int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret; unsigned char output_buf[4096]; size_t olen = 0; if( ( ret = mbedtls_x509write_csr_der( ctx, output_buf, sizeof(output_buf), f_rng, p_rng ) ) < 0 ) { return( ret ); } if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR, output_buf + sizeof(output_buf) - ret, ret, buf, size, &olen ) ) != 0 ) { return( ret ); } return( 0 ); }
/* * CSR is output formatted as b64url(DER) * Private key is output as a PEM in memory */ LWS_VISIBLE LWS_EXTERN int lws_tls_acme_sni_csr_create(struct lws_context *context, const char *elements[], uint8_t *dcsr, size_t csr_len, char **privkey_pem, size_t *privkey_len) { mbedtls_x509write_csr csr; char subject[200]; mbedtls_pk_context mpk; int buf_size = 4096, n; uint8_t *buf = malloc(buf_size); /* malloc because given to user code */ if (!buf) return -1; mbedtls_x509write_csr_init(&csr); mbedtls_pk_init(&mpk); if (mbedtls_pk_setup(&mpk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA))) { lwsl_notice("%s: pk_setup failed\n", __func__); goto fail; } n = mbedtls_rsa_gen_key(mbedtls_pk_rsa(mpk), _rngf, context, lws_plat_recommended_rsa_bits(), 65537); if (n) { lwsl_notice("%s: failed to generate keys\n", __func__); goto fail1; } /* subject must be formatted like "C=TW,O=warmcat,CN=myserver" */ lws_snprintf(subject, sizeof(subject) - 1, "C=%s,ST=%s,L=%s,O=%s,CN=%s", elements[LWS_TLS_REQ_ELEMENT_COUNTRY], elements[LWS_TLS_REQ_ELEMENT_STATE], elements[LWS_TLS_REQ_ELEMENT_LOCALITY], elements[LWS_TLS_REQ_ELEMENT_ORGANIZATION], elements[LWS_TLS_REQ_ELEMENT_COMMON_NAME]); if (mbedtls_x509write_csr_set_subject_name(&csr, subject)) goto fail1; mbedtls_x509write_csr_set_key(&csr, &mpk); mbedtls_x509write_csr_set_md_alg(&csr, MBEDTLS_MD_SHA256); /* * data is written at the end of the buffer! Use the * return value to determine where you should start * using the buffer */ n = mbedtls_x509write_csr_der(&csr, buf, buf_size, _rngf, context); if (n < 0) { lwsl_notice("%s: write csr der failed\n", __func__); goto fail1; } /* we have it in DER, we need it in b64URL */ n = lws_jws_base64_enc((char *)(buf + buf_size) - n, n, (char *)dcsr, csr_len); if (n < 0) goto fail1; /* * okay, the CSR is done, last we need the private key in PEM * re-use the DER CSR buf as the result buffer since we cn do it in * one step */ if (mbedtls_pk_write_key_pem(&mpk, buf, buf_size)) { lwsl_notice("write key pem failed\n"); goto fail1; } *privkey_pem = (char *)buf; *privkey_len = strlen((const char *)buf); mbedtls_pk_free(&mpk); mbedtls_x509write_csr_free(&csr); return n; fail1: mbedtls_pk_free(&mpk); fail: mbedtls_x509write_csr_free(&csr); free(buf); return -1; }