blob: 3a49aee94eb4e1b14c0b8a96c80da6c90a09d507 [file] [log] [blame]
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001/*
2 * X.509 Certificate Signing Request writing
3 *
4 * Copyright (C) 2006-2013, 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#include "polarssl/config.h"
32
33#if defined(POLARSSL_X509_CSR_WRITE_C)
34
35#include "polarssl/x509_csr.h"
36#include "polarssl/oid.h"
37#include "polarssl/asn1write.h"
38
39#if defined(POLARSSL_PEM_WRITE_C)
40#include "polarssl/pem.h"
41#endif
42
43#include <string.h>
44#include <stdlib.h>
45
46void x509write_csr_init( x509write_csr *ctx )
47{
48 memset( ctx, 0, sizeof(x509write_csr) );
49}
50
51void x509write_csr_free( x509write_csr *ctx )
52{
53 asn1_free_named_data_list( &ctx->subject );
54 asn1_free_named_data_list( &ctx->extensions );
55
56 memset( ctx, 0, sizeof(x509write_csr) );
57}
58
59void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg )
60{
61 ctx->md_alg = md_alg;
62}
63
64void x509write_csr_set_key( x509write_csr *ctx, pk_context *key )
65{
66 ctx->key = key;
67}
68
Paul Bakker50dc8502013-10-28 21:19:10 +010069int x509write_csr_set_subject_name( x509write_csr *ctx,
70 const char *subject_name )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020071{
Paul Bakker86d0c192013-09-18 11:11:02 +020072 return x509_string_to_names( &ctx->subject, subject_name );
Paul Bakker7c6b2c32013-09-16 13:49:26 +020073}
74
75int x509write_csr_set_extension( x509write_csr *ctx,
76 const char *oid, size_t oid_len,
77 const unsigned char *val, size_t val_len )
78{
79 return x509_set_extension( &ctx->extensions, oid, oid_len,
80 0, val, val_len );
81}
82
83int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage )
84{
85 unsigned char buf[4];
86 unsigned char *c;
87 int ret;
88
89 c = buf + 4;
90
91 if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
92 return( ret );
93
94 ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE,
95 OID_SIZE( OID_KEY_USAGE ),
96 buf, 4 );
97 if( ret != 0 )
98 return( ret );
99
100 return( 0 );
101}
102
103int x509write_csr_set_ns_cert_type( x509write_csr *ctx,
104 unsigned char ns_cert_type )
105{
106 unsigned char buf[4];
107 unsigned char *c;
108 int ret;
109
110 c = buf + 4;
111
112 if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
113 return( ret );
114
115 ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE,
116 OID_SIZE( OID_NS_CERT_TYPE ),
117 buf, 4 );
118 if( ret != 0 )
119 return( ret );
120
121 return( 0 );
122}
123
124int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size,
125 int (*f_rng)(void *, unsigned char *, size_t),
126 void *p_rng )
127{
128 int ret;
129 const char *sig_oid;
130 size_t sig_oid_len = 0;
131 unsigned char *c, *c2;
132 unsigned char hash[64];
133 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
134 unsigned char tmp_buf[2048];
135 size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
136 size_t len = 0;
137 pk_type_t pk_alg;
138
139 /*
140 * Prepare data to be signed in tmp_buf
141 */
142 c = tmp_buf + sizeof( tmp_buf );
143
144 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
145
146 if( len )
147 {
148 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
149 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
150
151 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
152 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) );
153
154 ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ,
155 OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) );
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 | ASN1_SEQUENCE ) );
159 }
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 | ASN1_CONTEXT_SPECIFIC ) );
163
164 ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->key,
165 tmp_buf, c - tmp_buf ) );
166 c -= pub_len;
167 len += pub_len;
168
169 /*
170 * Subject ::= Name
171 */
172 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
173
174 /*
175 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
176 */
177 ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
178
179 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
180 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
181
182 /*
183 * Prepare signature
184 */
185 md( md_info_from_type( ctx->md_alg ), c, len, hash );
186
187 pk_alg = pk_get_type( ctx->key );
188 if( pk_alg == POLARSSL_PK_ECKEY )
189 pk_alg = POLARSSL_PK_ECDSA;
190
191 if( ( ret = pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,
192 f_rng, p_rng ) ) != 0 ||
193 ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
194 &sig_oid, &sig_oid_len ) ) != 0 )
195 {
196 return( ret );
197 }
198
199 /*
200 * Write data to output buffer
201 */
202 c2 = buf + size;
203 ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf,
204 sig_oid, sig_oid_len, sig, sig_len ) );
205
206 c2 -= len;
207 memcpy( c2, c, len );
208
209 len += sig_and_oid_len;
210 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
211 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
212
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200213 return( (int) len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200214}
215
216#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n"
217#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n"
218
219#if defined(POLARSSL_PEM_WRITE_C)
220int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size,
221 int (*f_rng)(void *, unsigned char *, size_t),
222 void *p_rng )
223{
224 int ret;
225 unsigned char output_buf[4096];
226 size_t olen = 0;
227
228 if( ( ret = x509write_csr_der( ctx, output_buf, sizeof(output_buf),
229 f_rng, p_rng ) ) < 0 )
230 {
231 return( ret );
232 }
233
234 if( ( ret = pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR,
235 output_buf + sizeof(output_buf) - ret,
236 ret, buf, size, &olen ) ) != 0 )
237 {
238 return( ret );
239 }
240
241 return( 0 );
242}
243#endif /* POLARSSL_PEM_WRITE_C */
244
245#endif /* POLARSSL_X509_CSR_WRITE_C */