PolarSSL v1.3.8
x509write_csr.c
Go to the documentation of this file.
1 /*
2  * X.509 Certificate Signing Request writing
3  *
4  * Copyright (C) 2006-2014, Brainspark B.V.
5  *
6  * This file is part of PolarSSL (http://www.polarssl.org)
7  * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
8  *
9  * All rights reserved.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25 /*
26  * References:
27  * - CSRs: PKCS#10 v1.7 aka RFC 2986
28  * - attributes: PKCS#9 v2.0 aka RFC 2985
29  */
30 
31 #if !defined(POLARSSL_CONFIG_FILE)
32 #include "polarssl/config.h"
33 #else
34 #include POLARSSL_CONFIG_FILE
35 #endif
36 
37 #if defined(POLARSSL_X509_CSR_WRITE_C)
38 
39 #include "polarssl/x509_csr.h"
40 #include "polarssl/oid.h"
41 #include "polarssl/asn1write.h"
42 
43 #if defined(POLARSSL_PEM_WRITE_C)
44 #include "polarssl/pem.h"
45 #endif
46 
47 #include <string.h>
48 #include <stdlib.h>
49 
50 /* Implementation that should never be optimized out by the compiler */
51 static void polarssl_zeroize( void *v, size_t n ) {
52  volatile unsigned char *p = v; while( n-- ) *p++ = 0;
53 }
54 
56 {
57  memset( ctx, 0, sizeof(x509write_csr) );
58 }
59 
61 {
64 
65  polarssl_zeroize( ctx, sizeof(x509write_csr) );
66 }
67 
69 {
70  ctx->md_alg = md_alg;
71 }
72 
74 {
75  ctx->key = key;
76 }
77 
79  const char *subject_name )
80 {
81  return x509_string_to_names( &ctx->subject, subject_name );
82 }
83 
85  const char *oid, size_t oid_len,
86  const unsigned char *val, size_t val_len )
87 {
88  return x509_set_extension( &ctx->extensions, oid, oid_len,
89  0, val, val_len );
90 }
91 
92 int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage )
93 {
94  unsigned char buf[4];
95  unsigned char *c;
96  int ret;
97 
98  c = buf + 4;
99 
100  if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
101  return( ret );
102 
105  buf, 4 );
106  if( ret != 0 )
107  return( ret );
108 
109  return( 0 );
110 }
111 
113  unsigned char ns_cert_type )
114 {
115  unsigned char buf[4];
116  unsigned char *c;
117  int ret;
118 
119  c = buf + 4;
120 
121  if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
122  return( ret );
123 
126  buf, 4 );
127  if( ret != 0 )
128  return( ret );
129 
130  return( 0 );
131 }
132 
133 int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size,
134  int (*f_rng)(void *, unsigned char *, size_t),
135  void *p_rng )
136 {
137  int ret;
138  const char *sig_oid;
139  size_t sig_oid_len = 0;
140  unsigned char *c, *c2;
141  unsigned char hash[64];
142  unsigned char sig[POLARSSL_MPI_MAX_SIZE];
143  unsigned char tmp_buf[2048];
144  size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
145  size_t len = 0;
146  pk_type_t pk_alg;
147 
148  /*
149  * Prepare data to be signed in tmp_buf
150  */
151  c = tmp_buf + sizeof( tmp_buf );
152 
153  ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
154 
155  if( len )
156  {
157  ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
158  ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
159  ASN1_SEQUENCE ) );
160 
161  ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
162  ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
163  ASN1_SET ) );
164 
167 
168  ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
169  ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
170  ASN1_SEQUENCE ) );
171  }
172 
173  ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
174  ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
176 
177  ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->key,
178  tmp_buf, c - tmp_buf ) );
179  c -= pub_len;
180  len += pub_len;
181 
182  /*
183  * Subject ::= Name
184  */
185  ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
186 
187  /*
188  * Version ::= INTEGER { v1(0), v2(1), v3(2) }
189  */
190  ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
191 
192  ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
193  ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
194  ASN1_SEQUENCE ) );
195 
196  /*
197  * Prepare signature
198  */
199  md( md_info_from_type( ctx->md_alg ), c, len, hash );
200 
201  pk_alg = pk_get_type( ctx->key );
202  if( pk_alg == POLARSSL_PK_ECKEY )
203  pk_alg = POLARSSL_PK_ECDSA;
204 
205  if( ( ret = pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,
206  f_rng, p_rng ) ) != 0 ||
207  ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
208  &sig_oid, &sig_oid_len ) ) != 0 )
209  {
210  return( ret );
211  }
212 
213  /*
214  * Write data to output buffer
215  */
216  c2 = buf + size;
217  ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf,
218  sig_oid, sig_oid_len, sig, sig_len ) );
219 
220  c2 -= len;
221  memcpy( c2, c, len );
222 
223  len += sig_and_oid_len;
224  ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
225  ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED |
226  ASN1_SEQUENCE ) );
227 
228  return( (int) len );
229 }
230 
231 #define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n"
232 #define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n"
233 
234 #if defined(POLARSSL_PEM_WRITE_C)
235 int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size,
236  int (*f_rng)(void *, unsigned char *, size_t),
237  void *p_rng )
238 {
239  int ret;
240  unsigned char output_buf[4096];
241  size_t olen = 0;
242 
243  if( ( ret = x509write_csr_der( ctx, output_buf, sizeof(output_buf),
244  f_rng, p_rng ) ) < 0 )
245  {
246  return( ret );
247  }
248 
249  if( ( ret = pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR,
250  output_buf + sizeof(output_buf) - ret,
251  ret, buf, size, &olen ) ) != 0 )
252  {
253  return( ret );
254  }
255 
256  return( 0 );
257 }
258 #endif /* POLARSSL_PEM_WRITE_C */
259 
260 #endif /* POLARSSL_X509_CSR_WRITE_C */