Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  *  X.509 Certificate Signing Request writing
  3.  *
  4.  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
  5.  *  SPDX-License-Identifier: GPL-2.0
  6.  *
  7.  *  This program is free software; you can redistribute it and/or modify
  8.  *  it under the terms of the GNU General Public License as published by
  9.  *  the Free Software Foundation; either version 2 of the License, or
  10.  *  (at your option) any later version.
  11.  *
  12.  *  This program is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *  GNU General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU General Public License along
  18.  *  with this program; if not, write to the Free Software Foundation, Inc.,
  19.  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20.  *
  21.  *  This file is part of mbed TLS (https://tls.mbed.org)
  22.  */
  23. /*
  24.  * References:
  25.  * - CSRs: PKCS#10 v1.7 aka RFC 2986
  26.  * - attributes: PKCS#9 v2.0 aka RFC 2985
  27.  */
  28.  
  29. #if !defined(MBEDTLS_CONFIG_FILE)
  30. #include "mbedtls/config.h"
  31. #else
  32. #include MBEDTLS_CONFIG_FILE
  33. #endif
  34.  
  35. #if defined(MBEDTLS_X509_CSR_WRITE_C)
  36.  
  37. #include "mbedtls/x509_csr.h"
  38. #include "mbedtls/oid.h"
  39. #include "mbedtls/asn1write.h"
  40. #include "mbedtls/platform_util.h"
  41.  
  42. #include <string.h>
  43. #include <stdlib.h>
  44.  
  45. #if defined(MBEDTLS_PEM_WRITE_C)
  46. #include "mbedtls/pem.h"
  47. #endif
  48.  
  49. /*
  50.  * For the currently used signature algorithms the buffer to store any signature
  51.  * must be at least of size MAX(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE)
  52.  */
  53. #if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE
  54. #define SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN
  55. #else
  56. #define SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE
  57. #endif
  58.  
  59. void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx )
  60. {
  61.     memset( ctx, 0, sizeof( mbedtls_x509write_csr ) );
  62. }
  63.  
  64. void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx )
  65. {
  66.     mbedtls_asn1_free_named_data_list( &ctx->subject );
  67.     mbedtls_asn1_free_named_data_list( &ctx->extensions );
  68.  
  69.     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_csr ) );
  70. }
  71.  
  72. void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg )
  73. {
  74.     ctx->md_alg = md_alg;
  75. }
  76.  
  77. void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key )
  78. {
  79.     ctx->key = key;
  80. }
  81.  
  82. int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx,
  83.                                     const char *subject_name )
  84. {
  85.     return mbedtls_x509_string_to_names( &ctx->subject, subject_name );
  86. }
  87.  
  88. int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx,
  89.                                  const char *oid, size_t oid_len,
  90.                                  const unsigned char *val, size_t val_len )
  91. {
  92.     return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len,
  93.                                0, val, val_len );
  94. }
  95.  
  96. static size_t csr_get_unused_bits_for_named_bitstring( unsigned char bitstring,
  97.                                                        size_t bit_offset )
  98. {
  99.     size_t unused_bits;
  100.  
  101.      /* Count the unused bits removing trailing 0s */
  102.     for( unused_bits = bit_offset; unused_bits < 8; unused_bits++ )
  103.         if( ( ( bitstring >> unused_bits ) & 0x1 ) != 0 )
  104.             break;
  105.  
  106.      return( unused_bits );
  107. }
  108.  
  109. int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage )
  110. {
  111.     unsigned char buf[4];
  112.     unsigned char *c;
  113.     size_t unused_bits;
  114.     int ret;
  115.  
  116.     c = buf + 4;
  117.  
  118.     unused_bits = csr_get_unused_bits_for_named_bitstring( key_usage, 0 );
  119.     ret = mbedtls_asn1_write_bitstring( &c, buf, &key_usage, 8 - unused_bits );
  120.  
  121.     if( ret < 0 )
  122.         return( ret );
  123.     else if( ret < 3 || ret > 4 )
  124.         return( MBEDTLS_ERR_X509_INVALID_FORMAT );
  125.  
  126.     ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
  127.                                        MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
  128.                                        c, (size_t)ret );
  129.     if( ret != 0 )
  130.         return( ret );
  131.  
  132.     return( 0 );
  133. }
  134.  
  135. int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx,
  136.                                     unsigned char ns_cert_type )
  137. {
  138.     unsigned char buf[4];
  139.     unsigned char *c;
  140.     size_t unused_bits;
  141.     int ret;
  142.  
  143.     c = buf + 4;
  144.  
  145.     unused_bits = csr_get_unused_bits_for_named_bitstring( ns_cert_type, 0 );
  146.     ret = mbedtls_asn1_write_bitstring( &c,
  147.                                         buf,
  148.                                         &ns_cert_type,
  149.                                         8 - unused_bits );
  150.  
  151.     if( ret < 0 )
  152.         return( ret );
  153.     else if( ret < 3 || ret > 4 )
  154.         return( ret );
  155.  
  156.     ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
  157.                                        MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
  158.                                        c, (size_t)ret );
  159.     if( ret != 0 )
  160.         return( ret );
  161.  
  162.     return( 0 );
  163. }
  164.  
  165. int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size,
  166.                        int (*f_rng)(void *, unsigned char *, size_t),
  167.                        void *p_rng )
  168. {
  169.     int ret;
  170.     const char *sig_oid;
  171.     size_t sig_oid_len = 0;
  172.     unsigned char *c, *c2;
  173.     unsigned char hash[64];
  174.     unsigned char sig[SIGNATURE_MAX_SIZE];
  175.     unsigned char tmp_buf[2048];
  176.     size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
  177.     size_t len = 0;
  178.     mbedtls_pk_type_t pk_alg;
  179.  
  180.     /*
  181.      * Prepare data to be signed in tmp_buf
  182.      */
  183.     c = tmp_buf + sizeof( tmp_buf );
  184.  
  185.     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
  186.  
  187.     if( len )
  188.     {
  189.         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
  190.         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
  191.                                                         MBEDTLS_ASN1_SEQUENCE ) );
  192.  
  193.         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
  194.         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
  195.                                                         MBEDTLS_ASN1_SET ) );
  196.  
  197.         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( &c, tmp_buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ,
  198.                                           MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_CSR_EXT_REQ ) ) );
  199.  
  200.         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
  201.         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
  202.                                                         MBEDTLS_ASN1_SEQUENCE ) );
  203.     }
  204.  
  205.     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
  206.     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
  207.                                                     MBEDTLS_ASN1_CONTEXT_SPECIFIC ) );
  208.  
  209.     MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->key,
  210.                                                 tmp_buf, c - tmp_buf ) );
  211.     c -= pub_len;
  212.     len += pub_len;
  213.  
  214.     /*
  215.      *  Subject  ::=  Name
  216.      */
  217.     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) );
  218.  
  219.     /*
  220.      *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
  221.      */
  222.     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, tmp_buf, 0 ) );
  223.  
  224.     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
  225.     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
  226.                                                     MBEDTLS_ASN1_SEQUENCE ) );
  227.  
  228.     /*
  229.      * Prepare signature
  230.      */
  231.     ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash );
  232.     if( ret != 0 )
  233.         return( ret );
  234.  
  235.     if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,
  236.                                  f_rng, p_rng ) ) != 0 )
  237.     {
  238.         return( ret );
  239.     }
  240.  
  241.     if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_RSA ) )
  242.         pk_alg = MBEDTLS_PK_RSA;
  243.     else if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_ECDSA ) )
  244.         pk_alg = MBEDTLS_PK_ECDSA;
  245.     else
  246.         return( MBEDTLS_ERR_X509_INVALID_ALG );
  247.  
  248.     if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
  249.                                                 &sig_oid, &sig_oid_len ) ) != 0 )
  250.     {
  251.         return( ret );
  252.     }
  253.  
  254.     /*
  255.      * Write data to output buffer
  256.      */
  257.     c2 = buf + size;
  258.     MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf,
  259.                                         sig_oid, sig_oid_len, sig, sig_len ) );
  260.  
  261.     if( len > (size_t)( c2 - buf ) )
  262.         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
  263.  
  264.     c2 -= len;
  265.     memcpy( c2, c, len );
  266.  
  267.     len += sig_and_oid_len;
  268.     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) );
  269.     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED |
  270.                                                  MBEDTLS_ASN1_SEQUENCE ) );
  271.  
  272.     return( (int) len );
  273. }
  274.  
  275. #define PEM_BEGIN_CSR           "-----BEGIN CERTIFICATE REQUEST-----\n"
  276. #define PEM_END_CSR             "-----END CERTIFICATE REQUEST-----\n"
  277.  
  278. #if defined(MBEDTLS_PEM_WRITE_C)
  279. int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size,
  280.                        int (*f_rng)(void *, unsigned char *, size_t),
  281.                        void *p_rng )
  282. {
  283.     int ret;
  284.     unsigned char output_buf[4096];
  285.     size_t olen = 0;
  286.  
  287.     if( ( ret = mbedtls_x509write_csr_der( ctx, output_buf, sizeof(output_buf),
  288.                                    f_rng, p_rng ) ) < 0 )
  289.     {
  290.         return( ret );
  291.     }
  292.  
  293.     if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR,
  294.                                   output_buf + sizeof(output_buf) - ret,
  295.                                   ret, buf, size, &olen ) ) != 0 )
  296.     {
  297.         return( ret );
  298.     }
  299.  
  300.     return( 0 );
  301. }
  302. #endif /* MBEDTLS_PEM_WRITE_C */
  303.  
  304. #endif /* MBEDTLS_X509_CSR_WRITE_C */
  305.