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 */
int md(const md_info_t *md_info, const unsigned char *input, size_t ilen, unsigned char *output)
Output = message_digest( input buffer )
void x509write_csr_free(x509write_csr *ctx)
Free the contents of a CSR context.
int x509_set_extension(asn1_named_data **head, const char *oid, size_t oid_len, int critical, const unsigned char *val, size_t val_len)
int x509_string_to_names(asn1_named_data **head, const char *name)
int x509write_csr_der(x509write_csr *ctx, unsigned char *buf, size_t size, int(*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Write a CSR (Certificate Signing Request) to a DER structure Note: data is written at the end of the ...
int x509write_csr_set_extension(x509write_csr *ctx, const char *oid, size_t oid_len, const unsigned char *val, size_t val_len)
Generic function to add to or replace an extension in the CSR.
void x509write_csr_set_md_alg(x509write_csr *ctx, md_type_t md_alg)
Set the MD algorithm to use for the signature (e.g.
int x509write_csr_set_ns_cert_type(x509write_csr *ctx, unsigned char ns_cert_type)
Set the Netscape Cert Type flags (e.g.
#define ASN1_SEQUENCE
Definition: asn1.h:82
Configuration options (set of defines)
int x509write_csr_pem(x509write_csr *ctx, unsigned char *buf, size_t size, int(*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Write a CSR (Certificate Signing Request) to a PEM string.
#define ASN1_CONSTRUCTED
Definition: asn1.h:92
pk_type_t pk_get_type(const pk_context *ctx)
Get the key type.
#define OID_PKCS9_CSR_EXT_REQ
extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14}
Definition: oid.h:256
int x509write_csr_set_key_usage(x509write_csr *ctx, unsigned char key_usage)
Set the Key Usage Extension flags (e.g.
md_type_t md_alg
Definition: x509_csr.h:81
Object Identifier (OID) database.
#define OID_SIZE(x)
Returns the size of the binary string, without the trailing \0.
Definition: asn1.h:98
md_type_t
Definition: md.h:51
int asn1_write_len(unsigned char **p, unsigned char *start, size_t len)
Write a length field in ASN.1 format Note: function works backwards in data buffer.
#define POLARSSL_MPI_MAX_SIZE
#define ASN1_SET
Definition: asn1.h:83
int x509_write_names(unsigned char **p, unsigned char *start, asn1_named_data *first)
const md_info_t * md_info_from_type(md_type_t md_type)
Returns the message digest information associated with the given digest type.
int pk_write_pubkey_der(pk_context *ctx, unsigned char *buf, size_t size)
Write a public key to a SubjectPublicKeyInfo DER structure Note: data is written at the end of the bu...
Privacy Enhanced Mail (PEM) decoding.
asn1_named_data * subject
Definition: x509_csr.h:80
X.509 certificate signing request parsing and writing.
int x509_write_extensions(unsigned char **p, unsigned char *start, asn1_named_data *first)
void x509write_csr_init(x509write_csr *ctx)
Initialize a CSR context.
pk_type_t
Public key types.
Definition: pk.h:95
pk_context * key
Definition: x509_csr.h:79
#define ASN1_CONTEXT_SPECIFIC
Definition: asn1.h:93
void x509write_csr_set_key(x509write_csr *ctx, pk_context *key)
Set the key for a CSR (public key will be included, private key used to sign the CSR when writing it)...
asn1_named_data * extensions
Definition: x509_csr.h:82
int asn1_write_bitstring(unsigned char **p, unsigned char *start, const unsigned char *buf, size_t bits)
Write a bitstring tag (ASN1_BIT_STRING) and value in ASN.1 format Note: function works backwards in d...
int asn1_write_int(unsigned char **p, unsigned char *start, int val)
Write an int tag (ASN1_INTEGER) and value in ASN.1 format Note: function works backwards in data buff...
void asn1_free_named_data_list(asn1_named_data **head)
Free all entries in a asn1_named_data list Head will be set to NULL.
#define ASN1_CHK_ADD(g, f)
Definition: asn1write.h:32
int pk_sign(pk_context *ctx, md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t *sig_len, int(*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Make signature, including padding if relevant.
int x509write_csr_set_subject_name(x509write_csr *ctx, const char *subject_name)
Set the subject name for a CSR Subject names should contain a comma-separated list of OID types and v...
int x509_write_sig(unsigned char **p, unsigned char *start, const char *oid, size_t oid_len, unsigned char *sig, size_t size)
ASN.1 buffer writing functionality.
int asn1_write_oid(unsigned char **p, unsigned char *start, const char *oid, size_t oid_len)
Write an OID tag (ASN1_OID) and data in ASN.1 format Note: function works backwards in data buffer...
int asn1_write_tag(unsigned char **p, unsigned char *start, unsigned char tag)
Write a ASN.1 tag in ASN.1 format Note: function works backwards in data buffer.
#define OID_NS_CERT_TYPE
Definition: oid.h:153
Public key container.
Definition: pk.h:194
Container for writing a CSR.
Definition: x509_csr.h:77
int oid_get_oid_by_sig_alg(pk_type_t pk_alg, md_type_t md_alg, const char **oid, size_t *olen)
Translate md_type and pk_type into SignatureAlgorithm OID.
#define OID_KEY_USAGE
id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 }
Definition: oid.h:135