PolarSSL v1.3.7
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 
51 {
52  memset( ctx, 0, sizeof(x509write_csr) );
53 }
54 
56 {
59 
60  memset( ctx, 0, sizeof(x509write_csr) );
61 }
62 
64 {
65  ctx->md_alg = md_alg;
66 }
67 
69 {
70  ctx->key = key;
71 }
72 
74  const char *subject_name )
75 {
76  return x509_string_to_names( &ctx->subject, subject_name );
77 }
78 
80  const char *oid, size_t oid_len,
81  const unsigned char *val, size_t val_len )
82 {
83  return x509_set_extension( &ctx->extensions, oid, oid_len,
84  0, val, val_len );
85 }
86 
87 int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage )
88 {
89  unsigned char buf[4];
90  unsigned char *c;
91  int ret;
92 
93  c = buf + 4;
94 
95  if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
96  return( ret );
97 
100  buf, 4 );
101  if( ret != 0 )
102  return( ret );
103 
104  return( 0 );
105 }
106 
108  unsigned char ns_cert_type )
109 {
110  unsigned char buf[4];
111  unsigned char *c;
112  int ret;
113 
114  c = buf + 4;
115 
116  if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
117  return( ret );
118 
121  buf, 4 );
122  if( ret != 0 )
123  return( ret );
124 
125  return( 0 );
126 }
127 
128 int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size,
129  int (*f_rng)(void *, unsigned char *, size_t),
130  void *p_rng )
131 {
132  int ret;
133  const char *sig_oid;
134  size_t sig_oid_len = 0;
135  unsigned char *c, *c2;
136  unsigned char hash[64];
137  unsigned char sig[POLARSSL_MPI_MAX_SIZE];
138  unsigned char tmp_buf[2048];
139  size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
140  size_t len = 0;
141  pk_type_t pk_alg;
142 
143  /*
144  * Prepare data to be signed in tmp_buf
145  */
146  c = tmp_buf + sizeof( tmp_buf );
147 
148  ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
149 
150  if( len )
151  {
152  ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
153  ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
154  ASN1_SEQUENCE ) );
155 
156  ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
157  ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
158  ASN1_SET ) );
159 
162 
163  ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
164  ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
165  ASN1_SEQUENCE ) );
166  }
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 |
171 
172  ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->key,
173  tmp_buf, c - tmp_buf ) );
174  c -= pub_len;
175  len += pub_len;
176 
177  /*
178  * Subject ::= Name
179  */
180  ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
181 
182  /*
183  * Version ::= INTEGER { v1(0), v2(1), v3(2) }
184  */
185  ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
186 
187  ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
188  ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
189  ASN1_SEQUENCE ) );
190 
191  /*
192  * Prepare signature
193  */
194  md( md_info_from_type( ctx->md_alg ), c, len, hash );
195 
196  pk_alg = pk_get_type( ctx->key );
197  if( pk_alg == POLARSSL_PK_ECKEY )
198  pk_alg = POLARSSL_PK_ECDSA;
199 
200  if( ( ret = pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,
201  f_rng, p_rng ) ) != 0 ||
202  ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
203  &sig_oid, &sig_oid_len ) ) != 0 )
204  {
205  return( ret );
206  }
207 
208  /*
209  * Write data to output buffer
210  */
211  c2 = buf + size;
212  ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf,
213  sig_oid, sig_oid_len, sig, sig_len ) );
214 
215  c2 -= len;
216  memcpy( c2, c, len );
217 
218  len += sig_and_oid_len;
219  ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
220  ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED |
221  ASN1_SEQUENCE ) );
222 
223  return( (int) len );
224 }
225 
226 #define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n"
227 #define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n"
228 
229 #if defined(POLARSSL_PEM_WRITE_C)
230 int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size,
231  int (*f_rng)(void *, unsigned char *, size_t),
232  void *p_rng )
233 {
234  int ret;
235  unsigned char output_buf[4096];
236  size_t olen = 0;
237 
238  if( ( ret = x509write_csr_der( ctx, output_buf, sizeof(output_buf),
239  f_rng, p_rng ) ) < 0 )
240  {
241  return( ret );
242  }
243 
244  if( ( ret = pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR,
245  output_buf + sizeof(output_buf) - ret,
246  ret, buf, size, &olen ) ) != 0 )
247  {
248  return( ret );
249  }
250 
251  return( 0 );
252 }
253 #endif /* POLARSSL_PEM_WRITE_C */
254 
255 #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)
#define POLARSSL_MPI_MAX_SIZE
Maximum number of bytes for usable MPIs.
Definition: bignum.h:91
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:252
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:80
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 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:79
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:78
#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:81
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.
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:182
Container for writing a CSR.
Definition: x509_csr.h:76
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