PolarSSL v1.3.9
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 */
51static 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
92int 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
133int 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 ) );
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)
235int 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 */
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.
#define ASN1_CHK_ADD(g, f)
Definition asn1write.h:32
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_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.
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.
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...
#define POLARSSL_MPI_MAX_SIZE
Configuration options (set of defines)
#define OID_SIZE(x)
Returns the size of the binary string, without the trailing \0.
Definition asn1.h:98
#define ASN1_CONSTRUCTED
Definition asn1.h:92
#define ASN1_SEQUENCE
Definition asn1.h:82
#define ASN1_SET
Definition asn1.h:83
#define ASN1_CONTEXT_SPECIFIC
Definition asn1.h:93
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.
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 x509_string_to_names(asn1_named_data **head, const char *name)
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)
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.
int x509write_csr_set_ns_cert_type(x509write_csr *ctx, unsigned char ns_cert_type)
Set the Netscape Cert Type flags (e.g.
asn1_named_data * subject
Definition x509_csr.h:80
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)
void x509write_csr_free(x509write_csr *ctx)
Free the contents of a CSR context.
pk_context * key
Definition x509_csr.h:79
int x509write_csr_set_key_usage(x509write_csr *ctx, unsigned char key_usage)
Set the Key Usage Extension flags (e.g.
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...
md_type_t md_alg
Definition x509_csr.h:81
int x509_write_names(unsigned char **p, unsigned char *start, asn1_named_data *first)
int x509_write_sig(unsigned char **p, unsigned char *start, const char *oid, size_t oid_len, unsigned char *sig, size_t size)
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 ...
void x509write_csr_init(x509write_csr *ctx)
Initialize a CSR context.
int x509_write_extensions(unsigned char **p, unsigned char *start, asn1_named_data *first)
asn1_named_data * extensions
Definition x509_csr.h:82
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 md(const md_info_t *md_info, const unsigned char *input, size_t ilen, unsigned char *output)
Output = message_digest( input buffer )
md_type_t
Definition md.h:51
Object Identifier (OID) database.
#define OID_NS_CERT_TYPE
Definition oid.h:153
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_PKCS9_CSR_EXT_REQ
extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14}
Definition oid.h:256
#define OID_KEY_USAGE
id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 }
Definition oid.h:135
Privacy Enhanced Mail (PEM) decoding.
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...
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.
pk_type_t pk_get_type(const pk_context *ctx)
Get the key type.
pk_type_t
Public key types.
Definition pk.h:95
@ POLARSSL_PK_ECDSA
Definition pk.h:100
@ POLARSSL_PK_ECKEY
Definition pk.h:98
Container for writing a CSR.
Definition x509_csr.h:78
Public key container.
Definition pk.h:195
X.509 certificate signing request parsing and writing.