1817466cbSJens Wiklander /* 2817466cbSJens Wiklander * X.509 Certificate Signing Request writing 3817466cbSJens Wiklander * 47901324dSJerome Forissier * Copyright The Mbed TLS Contributors 57901324dSJerome Forissier * SPDX-License-Identifier: Apache-2.0 6817466cbSJens Wiklander * 7817466cbSJens Wiklander * Licensed under the Apache License, Version 2.0 (the "License"); you may 8817466cbSJens Wiklander * not use this file except in compliance with the License. 9817466cbSJens Wiklander * You may obtain a copy of the License at 10817466cbSJens Wiklander * 11817466cbSJens Wiklander * http://www.apache.org/licenses/LICENSE-2.0 12817466cbSJens Wiklander * 13817466cbSJens Wiklander * Unless required by applicable law or agreed to in writing, software 14817466cbSJens Wiklander * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15817466cbSJens Wiklander * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16817466cbSJens Wiklander * See the License for the specific language governing permissions and 17817466cbSJens Wiklander * limitations under the License. 18817466cbSJens Wiklander */ 19817466cbSJens Wiklander /* 20817466cbSJens Wiklander * References: 21817466cbSJens Wiklander * - CSRs: PKCS#10 v1.7 aka RFC 2986 22817466cbSJens Wiklander * - attributes: PKCS#9 v2.0 aka RFC 2985 23817466cbSJens Wiklander */ 24817466cbSJens Wiklander 257901324dSJerome Forissier #include "common.h" 26817466cbSJens Wiklander 27817466cbSJens Wiklander #if defined(MBEDTLS_X509_CSR_WRITE_C) 28817466cbSJens Wiklander 29*32b31808SJens Wiklander #include "mbedtls/x509.h" 30817466cbSJens Wiklander #include "mbedtls/x509_csr.h" 31817466cbSJens Wiklander #include "mbedtls/asn1write.h" 3211fa71b9SJerome Forissier #include "mbedtls/error.h" 3311fa71b9SJerome Forissier #include "mbedtls/oid.h" 343d3b0591SJens Wiklander #include "mbedtls/platform_util.h" 35817466cbSJens Wiklander 3611fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 3711fa71b9SJerome Forissier #include "psa/crypto.h" 3811fa71b9SJerome Forissier #include "mbedtls/psa_util.h" 39*32b31808SJens Wiklander #endif /* MBEDTLS_USE_PSA_CRYPTO */ 40*32b31808SJens Wiklander #include "hash_info.h" 4111fa71b9SJerome Forissier 42817466cbSJens Wiklander #include <string.h> 43817466cbSJens Wiklander #include <stdlib.h> 44817466cbSJens Wiklander 45817466cbSJens Wiklander #if defined(MBEDTLS_PEM_WRITE_C) 46817466cbSJens Wiklander #include "mbedtls/pem.h" 47817466cbSJens Wiklander #endif 48817466cbSJens Wiklander 497901324dSJerome Forissier #include "mbedtls/platform.h" 507901324dSJerome Forissier 51817466cbSJens Wiklander void mbedtls_x509write_csr_init(mbedtls_x509write_csr *ctx) 52817466cbSJens Wiklander { 53817466cbSJens Wiklander memset(ctx, 0, sizeof(mbedtls_x509write_csr)); 54817466cbSJens Wiklander } 55817466cbSJens Wiklander 56817466cbSJens Wiklander void mbedtls_x509write_csr_free(mbedtls_x509write_csr *ctx) 57817466cbSJens Wiklander { 58817466cbSJens Wiklander mbedtls_asn1_free_named_data_list(&ctx->subject); 59817466cbSJens Wiklander mbedtls_asn1_free_named_data_list(&ctx->extensions); 60817466cbSJens Wiklander 613d3b0591SJens Wiklander mbedtls_platform_zeroize(ctx, sizeof(mbedtls_x509write_csr)); 62817466cbSJens Wiklander } 63817466cbSJens Wiklander 64817466cbSJens Wiklander void mbedtls_x509write_csr_set_md_alg(mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg) 65817466cbSJens Wiklander { 66817466cbSJens Wiklander ctx->md_alg = md_alg; 67817466cbSJens Wiklander } 68817466cbSJens Wiklander 69817466cbSJens Wiklander void mbedtls_x509write_csr_set_key(mbedtls_x509write_csr *ctx, mbedtls_pk_context *key) 70817466cbSJens Wiklander { 71817466cbSJens Wiklander ctx->key = key; 72817466cbSJens Wiklander } 73817466cbSJens Wiklander 74817466cbSJens Wiklander int mbedtls_x509write_csr_set_subject_name(mbedtls_x509write_csr *ctx, 75817466cbSJens Wiklander const char *subject_name) 76817466cbSJens Wiklander { 77817466cbSJens Wiklander return mbedtls_x509_string_to_names(&ctx->subject, subject_name); 78817466cbSJens Wiklander } 79817466cbSJens Wiklander 80817466cbSJens Wiklander int mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr *ctx, 81817466cbSJens Wiklander const char *oid, size_t oid_len, 82*32b31808SJens Wiklander int critical, 83817466cbSJens Wiklander const unsigned char *val, size_t val_len) 84817466cbSJens Wiklander { 85817466cbSJens Wiklander return mbedtls_x509_set_extension(&ctx->extensions, oid, oid_len, 86*32b31808SJens Wiklander critical, val, val_len); 87*32b31808SJens Wiklander } 88*32b31808SJens Wiklander 89*32b31808SJens Wiklander int mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr *ctx, 90*32b31808SJens Wiklander const mbedtls_x509_san_list *san_list) 91*32b31808SJens Wiklander { 92*32b31808SJens Wiklander int ret = 0; 93*32b31808SJens Wiklander const mbedtls_x509_san_list *cur; 94*32b31808SJens Wiklander unsigned char *buf; 95*32b31808SJens Wiklander unsigned char *p; 96*32b31808SJens Wiklander size_t len; 97*32b31808SJens Wiklander size_t buflen = 0; 98*32b31808SJens Wiklander 99*32b31808SJens Wiklander /* Determine the maximum size of the SubjectAltName list */ 100*32b31808SJens Wiklander for (cur = san_list; cur != NULL; cur = cur->next) { 101*32b31808SJens Wiklander /* Calculate size of the required buffer */ 102*32b31808SJens Wiklander switch (cur->node.type) { 103*32b31808SJens Wiklander case MBEDTLS_X509_SAN_DNS_NAME: 104*32b31808SJens Wiklander case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: 105*32b31808SJens Wiklander case MBEDTLS_X509_SAN_IP_ADDRESS: 106*32b31808SJens Wiklander /* length of value for each name entry, 107*32b31808SJens Wiklander * maximum 4 bytes for the length field, 108*32b31808SJens Wiklander * 1 byte for the tag/type. 109*32b31808SJens Wiklander */ 110*32b31808SJens Wiklander buflen += cur->node.san.unstructured_name.len + 4 + 1; 111*32b31808SJens Wiklander break; 112*32b31808SJens Wiklander 113*32b31808SJens Wiklander default: 114*32b31808SJens Wiklander /* Not supported - skip. */ 115*32b31808SJens Wiklander break; 116*32b31808SJens Wiklander } 117*32b31808SJens Wiklander } 118*32b31808SJens Wiklander 119*32b31808SJens Wiklander /* Add the extra length field and tag */ 120*32b31808SJens Wiklander buflen += 4 + 1; 121*32b31808SJens Wiklander 122*32b31808SJens Wiklander /* Allocate buffer */ 123*32b31808SJens Wiklander buf = mbedtls_calloc(1, buflen); 124*32b31808SJens Wiklander if (buf == NULL) { 125*32b31808SJens Wiklander return MBEDTLS_ERR_ASN1_ALLOC_FAILED; 126*32b31808SJens Wiklander } 127*32b31808SJens Wiklander 128*32b31808SJens Wiklander mbedtls_platform_zeroize(buf, buflen); 129*32b31808SJens Wiklander p = buf + buflen; 130*32b31808SJens Wiklander 131*32b31808SJens Wiklander /* Write ASN.1-based structure */ 132*32b31808SJens Wiklander cur = san_list; 133*32b31808SJens Wiklander len = 0; 134*32b31808SJens Wiklander while (cur != NULL) { 135*32b31808SJens Wiklander switch (cur->node.type) { 136*32b31808SJens Wiklander case MBEDTLS_X509_SAN_DNS_NAME: 137*32b31808SJens Wiklander case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: 138*32b31808SJens Wiklander case MBEDTLS_X509_SAN_IP_ADDRESS: 139*32b31808SJens Wiklander { 140*32b31808SJens Wiklander const unsigned char *unstructured_name = 141*32b31808SJens Wiklander (const unsigned char *) cur->node.san.unstructured_name.p; 142*32b31808SJens Wiklander size_t unstructured_name_len = cur->node.san.unstructured_name.len; 143*32b31808SJens Wiklander 144*32b31808SJens Wiklander MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, 145*32b31808SJens Wiklander mbedtls_asn1_write_raw_buffer( 146*32b31808SJens Wiklander &p, buf, 147*32b31808SJens Wiklander unstructured_name, unstructured_name_len)); 148*32b31808SJens Wiklander MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_len( 149*32b31808SJens Wiklander &p, buf, unstructured_name_len)); 150*32b31808SJens Wiklander MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, 151*32b31808SJens Wiklander mbedtls_asn1_write_tag( 152*32b31808SJens Wiklander &p, buf, 153*32b31808SJens Wiklander MBEDTLS_ASN1_CONTEXT_SPECIFIC | cur->node.type)); 154*32b31808SJens Wiklander } 155*32b31808SJens Wiklander break; 156*32b31808SJens Wiklander default: 157*32b31808SJens Wiklander /* Skip unsupported names. */ 158*32b31808SJens Wiklander break; 159*32b31808SJens Wiklander } 160*32b31808SJens Wiklander cur = cur->next; 161*32b31808SJens Wiklander } 162*32b31808SJens Wiklander 163*32b31808SJens Wiklander MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_len(&p, buf, len)); 164*32b31808SJens Wiklander MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, 165*32b31808SJens Wiklander mbedtls_asn1_write_tag(&p, buf, 166*32b31808SJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | 167*32b31808SJens Wiklander MBEDTLS_ASN1_SEQUENCE)); 168*32b31808SJens Wiklander 169*32b31808SJens Wiklander ret = mbedtls_x509write_csr_set_extension( 170*32b31808SJens Wiklander ctx, 171*32b31808SJens Wiklander MBEDTLS_OID_SUBJECT_ALT_NAME, 172*32b31808SJens Wiklander MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_ALT_NAME), 173*32b31808SJens Wiklander 0, 174*32b31808SJens Wiklander buf + buflen - len, 175*32b31808SJens Wiklander len); 176*32b31808SJens Wiklander 177*32b31808SJens Wiklander /* If we exceeded the allocated buffer it means that maximum size of the SubjectAltName list 178*32b31808SJens Wiklander * was incorrectly calculated and memory is corrupted. */ 179*32b31808SJens Wiklander if (p < buf) { 180*32b31808SJens Wiklander ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; 181*32b31808SJens Wiklander } 182*32b31808SJens Wiklander 183*32b31808SJens Wiklander cleanup: 184*32b31808SJens Wiklander mbedtls_free(buf); 185*32b31808SJens Wiklander return ret; 186817466cbSJens Wiklander } 187817466cbSJens Wiklander 188817466cbSJens Wiklander int mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, unsigned char key_usage) 189817466cbSJens Wiklander { 1907901324dSJerome Forissier unsigned char buf[4] = { 0 }; 191817466cbSJens Wiklander unsigned char *c; 19211fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 193817466cbSJens Wiklander 194817466cbSJens Wiklander c = buf + 4; 195817466cbSJens Wiklander 19611fa71b9SJerome Forissier ret = mbedtls_asn1_write_named_bitstring(&c, buf, &key_usage, 8); 197*32b31808SJens Wiklander if (ret < 3 || ret > 4) { 198*32b31808SJens Wiklander return ret; 199*32b31808SJens Wiklander } 200817466cbSJens Wiklander 201817466cbSJens Wiklander ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_KEY_USAGE, 202817466cbSJens Wiklander MBEDTLS_OID_SIZE(MBEDTLS_OID_KEY_USAGE), 203*32b31808SJens Wiklander 0, c, (size_t) ret); 204*32b31808SJens Wiklander if (ret != 0) { 205*32b31808SJens Wiklander return ret; 206*32b31808SJens Wiklander } 207817466cbSJens Wiklander 208*32b31808SJens Wiklander return 0; 209817466cbSJens Wiklander } 210817466cbSJens Wiklander 211817466cbSJens Wiklander int mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr *ctx, 212817466cbSJens Wiklander unsigned char ns_cert_type) 213817466cbSJens Wiklander { 2147901324dSJerome Forissier unsigned char buf[4] = { 0 }; 215817466cbSJens Wiklander unsigned char *c; 21611fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 217817466cbSJens Wiklander 218817466cbSJens Wiklander c = buf + 4; 219817466cbSJens Wiklander 22011fa71b9SJerome Forissier ret = mbedtls_asn1_write_named_bitstring(&c, buf, &ns_cert_type, 8); 221*32b31808SJens Wiklander if (ret < 3 || ret > 4) { 222*32b31808SJens Wiklander return ret; 223*32b31808SJens Wiklander } 224817466cbSJens Wiklander 225817466cbSJens Wiklander ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_NS_CERT_TYPE, 226817466cbSJens Wiklander MBEDTLS_OID_SIZE(MBEDTLS_OID_NS_CERT_TYPE), 227*32b31808SJens Wiklander 0, c, (size_t) ret); 228*32b31808SJens Wiklander if (ret != 0) { 229*32b31808SJens Wiklander return ret; 230*32b31808SJens Wiklander } 231817466cbSJens Wiklander 232*32b31808SJens Wiklander return 0; 233817466cbSJens Wiklander } 234817466cbSJens Wiklander 2357901324dSJerome Forissier static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx, 2367901324dSJerome Forissier unsigned char *buf, 2377901324dSJerome Forissier size_t size, 238*32b31808SJens Wiklander unsigned char *sig, size_t sig_size, 239817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 240817466cbSJens Wiklander void *p_rng) 241817466cbSJens Wiklander { 24211fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 243817466cbSJens Wiklander const char *sig_oid; 244817466cbSJens Wiklander size_t sig_oid_len = 0; 245817466cbSJens Wiklander unsigned char *c, *c2; 246*32b31808SJens Wiklander unsigned char hash[MBEDTLS_HASH_MAX_SIZE]; 247817466cbSJens Wiklander size_t pub_len = 0, sig_and_oid_len = 0, sig_len; 248817466cbSJens Wiklander size_t len = 0; 249817466cbSJens Wiklander mbedtls_pk_type_t pk_alg; 25011fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 25111fa71b9SJerome Forissier size_t hash_len; 252*32b31808SJens Wiklander psa_algorithm_t hash_alg = mbedtls_hash_info_psa_from_md(ctx->md_alg); 25311fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */ 254817466cbSJens Wiklander 2557901324dSJerome Forissier /* Write the CSR backwards starting from the end of buf */ 2567901324dSJerome Forissier c = buf + size; 2577901324dSJerome Forissier 2587901324dSJerome Forissier MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_extensions(&c, buf, 2597901324dSJerome Forissier ctx->extensions)); 260817466cbSJens Wiklander 261*32b31808SJens Wiklander if (len) { 2627901324dSJerome Forissier MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 2637901324dSJerome Forissier MBEDTLS_ASN1_CHK_ADD(len, 2647901324dSJerome Forissier mbedtls_asn1_write_tag( 2657901324dSJerome Forissier &c, buf, 2667901324dSJerome Forissier MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); 267817466cbSJens Wiklander 2687901324dSJerome Forissier MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 2697901324dSJerome Forissier MBEDTLS_ASN1_CHK_ADD(len, 2707901324dSJerome Forissier mbedtls_asn1_write_tag( 2717901324dSJerome Forissier &c, buf, 2727901324dSJerome Forissier MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)); 273817466cbSJens Wiklander 2747901324dSJerome Forissier MBEDTLS_ASN1_CHK_ADD(len, 2757901324dSJerome Forissier mbedtls_asn1_write_oid( 2767901324dSJerome Forissier &c, buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ, 277817466cbSJens Wiklander MBEDTLS_OID_SIZE(MBEDTLS_OID_PKCS9_CSR_EXT_REQ))); 278817466cbSJens Wiklander 2797901324dSJerome Forissier MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 2807901324dSJerome Forissier MBEDTLS_ASN1_CHK_ADD(len, 2817901324dSJerome Forissier mbedtls_asn1_write_tag( 2827901324dSJerome Forissier &c, buf, 2837901324dSJerome Forissier MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); 284817466cbSJens Wiklander } 285817466cbSJens Wiklander 2867901324dSJerome Forissier MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 2877901324dSJerome Forissier MBEDTLS_ASN1_CHK_ADD(len, 2887901324dSJerome Forissier mbedtls_asn1_write_tag( 2897901324dSJerome Forissier &c, buf, 2907901324dSJerome Forissier MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)); 291817466cbSJens Wiklander 292817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_pk_write_pubkey_der(ctx->key, 2937901324dSJerome Forissier buf, c - buf)); 294817466cbSJens Wiklander c -= pub_len; 295817466cbSJens Wiklander len += pub_len; 296817466cbSJens Wiklander 297817466cbSJens Wiklander /* 298817466cbSJens Wiklander * Subject ::= Name 299817466cbSJens Wiklander */ 3007901324dSJerome Forissier MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf, 3017901324dSJerome Forissier ctx->subject)); 302817466cbSJens Wiklander 303817466cbSJens Wiklander /* 304817466cbSJens Wiklander * Version ::= INTEGER { v1(0), v2(1), v3(2) } 305817466cbSJens Wiklander */ 3067901324dSJerome Forissier MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 0)); 307817466cbSJens Wiklander 3087901324dSJerome Forissier MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 3097901324dSJerome Forissier MBEDTLS_ASN1_CHK_ADD(len, 3107901324dSJerome Forissier mbedtls_asn1_write_tag( 3117901324dSJerome Forissier &c, buf, 3127901324dSJerome Forissier MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); 313817466cbSJens Wiklander 314817466cbSJens Wiklander /* 3157901324dSJerome Forissier * Sign the written CSR data into the sig buffer 31611fa71b9SJerome Forissier * Note: hash errors can happen only after an internal error 317817466cbSJens Wiklander */ 31811fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO) 319*32b31808SJens Wiklander if (psa_hash_compute(hash_alg, 320*32b31808SJens Wiklander c, 321*32b31808SJens Wiklander len, 322*32b31808SJens Wiklander hash, 323*32b31808SJens Wiklander sizeof(hash), 324*32b31808SJens Wiklander &hash_len) != PSA_SUCCESS) { 325*32b31808SJens Wiklander return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 32611fa71b9SJerome Forissier } 32711fa71b9SJerome Forissier #else /* MBEDTLS_USE_PSA_CRYPTO */ 3285b25c76aSJerome Forissier ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c, len, hash); 329*32b31808SJens Wiklander if (ret != 0) { 330*32b31808SJens Wiklander return ret; 331*32b31808SJens Wiklander } 33211fa71b9SJerome Forissier #endif 333*32b31808SJens Wiklander if ((ret = mbedtls_pk_sign(ctx->key, ctx->md_alg, hash, 0, 334*32b31808SJens Wiklander sig, sig_size, &sig_len, 335*32b31808SJens Wiklander f_rng, p_rng)) != 0) { 336*32b31808SJens Wiklander return ret; 3373d3b0591SJens Wiklander } 3383d3b0591SJens Wiklander 339*32b31808SJens Wiklander if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_RSA)) { 3403d3b0591SJens Wiklander pk_alg = MBEDTLS_PK_RSA; 341*32b31808SJens Wiklander } else if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_ECDSA)) { 3423d3b0591SJens Wiklander pk_alg = MBEDTLS_PK_ECDSA; 343*32b31808SJens Wiklander } else { 344*32b31808SJens Wiklander return MBEDTLS_ERR_X509_INVALID_ALG; 345*32b31808SJens Wiklander } 3463d3b0591SJens Wiklander 3473d3b0591SJens Wiklander if ((ret = mbedtls_oid_get_oid_by_sig_alg(pk_alg, ctx->md_alg, 348*32b31808SJens Wiklander &sig_oid, &sig_oid_len)) != 0) { 349*32b31808SJens Wiklander return ret; 350817466cbSJens Wiklander } 351817466cbSJens Wiklander 352817466cbSJens Wiklander /* 3537901324dSJerome Forissier * Move the written CSR data to the start of buf to create space for 3547901324dSJerome Forissier * writing the signature into buf. 3557901324dSJerome Forissier */ 3567901324dSJerome Forissier memmove(buf, c, len); 3577901324dSJerome Forissier 3587901324dSJerome Forissier /* 3597901324dSJerome Forissier * Write sig and its OID into buf backwards from the end of buf. 3607901324dSJerome Forissier * Note: mbedtls_x509_write_sig will check for c2 - ( buf + len ) < sig_len 3617901324dSJerome Forissier * and return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if needed. 362817466cbSJens Wiklander */ 363817466cbSJens Wiklander c2 = buf + size; 3647901324dSJerome Forissier MBEDTLS_ASN1_CHK_ADD(sig_and_oid_len, 3657901324dSJerome Forissier mbedtls_x509_write_sig(&c2, buf + len, sig_oid, sig_oid_len, 3667901324dSJerome Forissier sig, sig_len)); 367817466cbSJens Wiklander 3687901324dSJerome Forissier /* 3697901324dSJerome Forissier * Compact the space between the CSR data and signature by moving the 3707901324dSJerome Forissier * CSR data to the start of the signature. 3717901324dSJerome Forissier */ 372817466cbSJens Wiklander c2 -= len; 3737901324dSJerome Forissier memmove(c2, buf, len); 374817466cbSJens Wiklander 3757901324dSJerome Forissier /* ASN encode the total size and tag the CSR data with it. */ 376817466cbSJens Wiklander len += sig_and_oid_len; 377817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c2, buf, len)); 3787901324dSJerome Forissier MBEDTLS_ASN1_CHK_ADD(len, 3797901324dSJerome Forissier mbedtls_asn1_write_tag( 3807901324dSJerome Forissier &c2, buf, 3817901324dSJerome Forissier MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); 3827901324dSJerome Forissier 3837901324dSJerome Forissier /* Zero the unused bytes at the start of buf */ 3847901324dSJerome Forissier memset(buf, 0, c2 - buf); 385817466cbSJens Wiklander 386*32b31808SJens Wiklander return (int) len; 387817466cbSJens Wiklander } 388817466cbSJens Wiklander 3897901324dSJerome Forissier int mbedtls_x509write_csr_der(mbedtls_x509write_csr *ctx, unsigned char *buf, 3907901324dSJerome Forissier size_t size, 3917901324dSJerome Forissier int (*f_rng)(void *, unsigned char *, size_t), 3927901324dSJerome Forissier void *p_rng) 3937901324dSJerome Forissier { 3947901324dSJerome Forissier int ret; 3957901324dSJerome Forissier unsigned char *sig; 3967901324dSJerome Forissier 397*32b31808SJens Wiklander if ((sig = mbedtls_calloc(1, MBEDTLS_PK_SIGNATURE_MAX_SIZE)) == NULL) { 398*32b31808SJens Wiklander return MBEDTLS_ERR_X509_ALLOC_FAILED; 3997901324dSJerome Forissier } 4007901324dSJerome Forissier 401*32b31808SJens Wiklander ret = x509write_csr_der_internal(ctx, buf, size, 402*32b31808SJens Wiklander sig, MBEDTLS_PK_SIGNATURE_MAX_SIZE, 403*32b31808SJens Wiklander f_rng, p_rng); 4047901324dSJerome Forissier 4057901324dSJerome Forissier mbedtls_free(sig); 4067901324dSJerome Forissier 407*32b31808SJens Wiklander return ret; 4087901324dSJerome Forissier } 4097901324dSJerome Forissier 410817466cbSJens Wiklander #define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" 411817466cbSJens Wiklander #define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" 412817466cbSJens Wiklander 413817466cbSJens Wiklander #if defined(MBEDTLS_PEM_WRITE_C) 414817466cbSJens Wiklander int mbedtls_x509write_csr_pem(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, 415817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 416817466cbSJens Wiklander void *p_rng) 417817466cbSJens Wiklander { 41811fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 419817466cbSJens Wiklander size_t olen = 0; 420817466cbSJens Wiklander 42111fa71b9SJerome Forissier if ((ret = mbedtls_x509write_csr_der(ctx, buf, size, 422*32b31808SJens Wiklander f_rng, p_rng)) < 0) { 423*32b31808SJens Wiklander return ret; 424817466cbSJens Wiklander } 425817466cbSJens Wiklander 426817466cbSJens Wiklander if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_CSR, PEM_END_CSR, 42711fa71b9SJerome Forissier buf + size - ret, 428*32b31808SJens Wiklander ret, buf, size, &olen)) != 0) { 429*32b31808SJens Wiklander return ret; 430817466cbSJens Wiklander } 431817466cbSJens Wiklander 432*32b31808SJens Wiklander return 0; 433817466cbSJens Wiklander } 434817466cbSJens Wiklander #endif /* MBEDTLS_PEM_WRITE_C */ 435817466cbSJens Wiklander 436817466cbSJens Wiklander #endif /* MBEDTLS_X509_CSR_WRITE_C */ 437