blob: 53ae9c63b744d98e1bed367a99e7467fb4f87ea9 [file] [log] [blame] [raw]
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001/*
2 * X.509 Certificate Signing Request writing
3 *
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +02004 * Copyright (C) 2006-2014, Brainspark B.V.
Paul Bakker7c6b2c32013-09-16 13:49:26 +02005 *
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
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020031#if !defined(POLARSSL_CONFIG_FILE)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020032#include "polarssl/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020033#else
34#include POLARSSL_CONFIG_FILE
35#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +020036
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
Paul Bakker34617722014-06-13 17:20:13 +020050/* 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
Paul Bakker7c6b2c32013-09-16 13:49:26 +020055void x509write_csr_init( x509write_csr *ctx )
56{
57 memset( ctx, 0, sizeof(x509write_csr) );
58}
59
60void x509write_csr_free( x509write_csr *ctx )
61{
62 asn1_free_named_data_list( &ctx->subject );
63 asn1_free_named_data_list( &ctx->extensions );
64
Paul Bakker34617722014-06-13 17:20:13 +020065 polarssl_zeroize( ctx, sizeof(x509write_csr) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +020066}
67
68void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg )
69{
70 ctx->md_alg = md_alg;
71}
72
73void x509write_csr_set_key( x509write_csr *ctx, pk_context *key )
74{
75 ctx->key = key;
76}
77
Paul Bakker50dc8502013-10-28 21:19:10 +010078int x509write_csr_set_subject_name( x509write_csr *ctx,
79 const char *subject_name )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020080{
Paul Bakker86d0c192013-09-18 11:11:02 +020081 return x509_string_to_names( &ctx->subject, subject_name );
Paul Bakker7c6b2c32013-09-16 13:49:26 +020082}
83
84int x509write_csr_set_extension( x509write_csr *ctx,
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
103 ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE,
104 OID_SIZE( OID_KEY_USAGE ),
105 buf, 4 );
106 if( ret != 0 )
107 return( ret );
108
109 return( 0 );
110}
111
112int x509write_csr_set_ns_cert_type( x509write_csr *ctx,
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
124 ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE,
125 OID_SIZE( OID_NS_CERT_TYPE ),
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 ) );
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200158 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
159 ASN1_SEQUENCE ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200160
161 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200162 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
163 ASN1_SET ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200164
165 ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ,
166 OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) );
167
168 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200169 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
170 ASN1_SEQUENCE ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200171 }
172
173 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200174 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
175 ASN1_CONTEXT_SPECIFIC ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200176
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 ) );
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200193 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
194 ASN1_SEQUENCE ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200195
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 ) );
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200225 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED |
226 ASN1_SEQUENCE ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200227
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200228 return( (int) len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200229}
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 */