blob: 2231206fc87f6668f2b8c8e7e057aea6fee8a394 [file] [log] [blame]
Paul Bakkerbdb912d2012-02-13 23:11:30 +00001/*
2 * X509 buffer writing functionality
3 *
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +02004 * Copyright (C) 2006-2013, Brainspark B.V.
Paul Bakkerbdb912d2012-02-13 23:11:30 +00005 *
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
Manuel Pégourié-Gonnardd4eb5b52013-09-11 18:16:20 +020026/*
27 * References:
28 * - certificates: RFC 5280, updated by RFC 6818
29 * - CSRs: PKCS#10 v1.7 aka RFC 2986
30 * - attributes: PKCS#9 v2.0 aka RFC 2985
31 */
32
Paul Bakkerbdb912d2012-02-13 23:11:30 +000033#include "polarssl/config.h"
34
35#if defined(POLARSSL_X509_WRITE_C)
36
37#include "polarssl/asn1write.h"
38#include "polarssl/x509write.h"
39#include "polarssl/x509.h"
Paul Bakkerc70b9822013-04-07 22:00:46 +020040#include "polarssl/md.h"
41#include "polarssl/oid.h"
Paul Bakkerbdb912d2012-02-13 23:11:30 +000042
Paul Bakker15162a02013-09-06 19:27:21 +020043#include "polarssl/sha1.h"
44
Paul Bakker135f1e92013-08-26 16:54:13 +020045#if defined(POLARSSL_BASE64_C)
46#include "polarssl/base64.h"
47#endif
48
Paul Bakker8eabfc12013-08-25 10:18:25 +020049#if defined(POLARSSL_MEMORY_C)
50#include "polarssl/memory.h"
51#else
52#include <stdlib.h>
53#define polarssl_malloc malloc
54#define polarssl_free free
55#endif
56
Paul Bakker5f45e622013-09-09 12:02:36 +020057static int x509write_string_to_names( asn1_named_data **head, char *name )
Paul Bakker8eabfc12013-08-25 10:18:25 +020058{
59 int ret = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +020060 char *s = name, *c = s;
Paul Bakker8eabfc12013-08-25 10:18:25 +020061 char *end = s + strlen( s );
62 char *oid = NULL;
63 int in_tag = 1;
Paul Bakker5f45e622013-09-09 12:02:36 +020064 asn1_named_data *cur;
Paul Bakker8eabfc12013-08-25 10:18:25 +020065
Manuel Pégourié-Gonnardda7317e2013-09-10 15:52:52 +020066 /* Clear existing chain if present */
67 asn1_free_named_data_list( head );
Paul Bakker8eabfc12013-08-25 10:18:25 +020068
69 while( c <= end )
70 {
71 if( in_tag && *c == '=' )
72 {
73 if( memcmp( s, "CN", 2 ) == 0 && c - s == 2 )
74 oid = OID_AT_CN;
75 else if( memcmp( s, "C", 1 ) == 0 && c - s == 1 )
76 oid = OID_AT_COUNTRY;
77 else if( memcmp( s, "O", 1 ) == 0 && c - s == 1 )
78 oid = OID_AT_ORGANIZATION;
79 else if( memcmp( s, "L", 1 ) == 0 && c - s == 1 )
80 oid = OID_AT_LOCALITY;
81 else if( memcmp( s, "R", 1 ) == 0 && c - s == 1 )
82 oid = OID_PKCS9_EMAIL;
83 else if( memcmp( s, "OU", 2 ) == 0 && c - s == 2 )
84 oid = OID_AT_ORG_UNIT;
85 else if( memcmp( s, "ST", 2 ) == 0 && c - s == 2 )
86 oid = OID_AT_STATE;
87 else
88 {
Paul Bakker0e06c0f2013-08-25 11:21:30 +020089 ret = POLARSSL_ERR_X509WRITE_UNKNOWN_OID;
Paul Bakker8eabfc12013-08-25 10:18:25 +020090 goto exit;
91 }
92
93 s = c + 1;
94 in_tag = 0;
95 }
96
97 if( !in_tag && ( *c == ',' || c == end ) )
98 {
Paul Bakker5f45e622013-09-09 12:02:36 +020099 if( ( cur = asn1_store_named_data( head, oid, strlen( oid ),
100 (unsigned char *) s,
101 c - s ) ) == NULL )
Paul Bakker8eabfc12013-08-25 10:18:25 +0200102 {
Paul Bakker5f45e622013-09-09 12:02:36 +0200103 return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
Paul Bakker8eabfc12013-08-25 10:18:25 +0200104 }
105
Paul Bakkerd4bf8702013-09-09 13:59:11 +0200106 while( c < end && *(c + 1) == ' ' )
107 c++;
108
Paul Bakker8eabfc12013-08-25 10:18:25 +0200109 s = c + 1;
110 in_tag = 1;
111 }
112 c++;
113 }
114
115exit:
116
117 return( ret );
118}
119
Paul Bakkercd358032013-09-09 12:08:11 +0200120void x509write_csr_init( x509write_csr *ctx )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200121{
Paul Bakkercd358032013-09-09 12:08:11 +0200122 memset( ctx, 0, sizeof(x509write_csr) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200123}
124
Paul Bakkercd358032013-09-09 12:08:11 +0200125void x509write_csr_free( x509write_csr *ctx )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200126{
Paul Bakker5f45e622013-09-09 12:02:36 +0200127 asn1_free_named_data_list( &ctx->subject );
128 asn1_free_named_data_list( &ctx->extensions );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200129
Paul Bakkercd358032013-09-09 12:08:11 +0200130 memset( ctx, 0, sizeof(x509write_csr) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200131}
132
Paul Bakkercd358032013-09-09 12:08:11 +0200133void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200134{
135 ctx->md_alg = md_alg;
136}
137
Manuel Pégourié-Gonnardee731792013-09-11 22:48:40 +0200138void x509write_csr_set_key( x509write_csr *ctx, pk_context *key )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200139{
Manuel Pégourié-Gonnardee731792013-09-11 22:48:40 +0200140 ctx->key = key;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200141}
142
Paul Bakkercd358032013-09-09 12:08:11 +0200143int x509write_csr_set_subject_name( x509write_csr *ctx, char *subject_name )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200144{
145 return x509write_string_to_names( &ctx->subject, subject_name );
146}
147
Paul Bakker15162a02013-09-06 19:27:21 +0200148/* The first byte of the value in the asn1_named_data structure is reserved
149 * to store the critical boolean for us
150 */
151static int x509_set_extension( asn1_named_data **head,
152 const char *oid, size_t oid_len,
153 int critical,
154 const unsigned char *val, size_t val_len )
Paul Bakkerfde42702013-08-25 14:47:27 +0200155{
Paul Bakkere5eae762013-08-26 12:05:14 +0200156 asn1_named_data *cur;
Paul Bakkere5eae762013-08-26 12:05:14 +0200157
Paul Bakker59ba59f2013-09-09 11:26:00 +0200158 if( ( cur = asn1_store_named_data( head, oid, oid_len,
159 NULL, val_len + 1 ) ) == NULL )
Paul Bakkere5eae762013-08-26 12:05:14 +0200160 {
Paul Bakker59ba59f2013-09-09 11:26:00 +0200161 return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
Paul Bakker1c0e5502013-08-26 13:41:01 +0200162 }
163
Paul Bakker15162a02013-09-06 19:27:21 +0200164 cur->val.p[0] = critical;
165 memcpy( cur->val.p + 1, val, val_len );
Paul Bakker1c0e5502013-08-26 13:41:01 +0200166
167 return( 0 );
168}
169
Paul Bakkercd358032013-09-09 12:08:11 +0200170int x509write_csr_set_extension( x509write_csr *ctx,
Paul Bakker15162a02013-09-06 19:27:21 +0200171 const char *oid, size_t oid_len,
172 const unsigned char *val, size_t val_len )
173{
174 return x509_set_extension( &ctx->extensions, oid, oid_len,
175 0, val, val_len );
176}
177
Paul Bakkercd358032013-09-09 12:08:11 +0200178int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200179{
180 unsigned char buf[4];
181 unsigned char *c;
182 int ret;
183
184 c = buf + 4;
185
Paul Bakker624d03a2013-08-26 14:12:57 +0200186 if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200187 return( ret );
188
189 ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE,
190 OID_SIZE( OID_KEY_USAGE ),
191 buf, 4 );
192 if( ret != 0 )
193 return( ret );
194
195 return( 0 );
196}
197
Paul Bakkercd358032013-09-09 12:08:11 +0200198int x509write_csr_set_ns_cert_type( x509write_csr *ctx,
199 unsigned char ns_cert_type )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200200{
201 unsigned char buf[4];
202 unsigned char *c;
203 int ret;
204
205 c = buf + 4;
206
207 if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
208 return( ret );
209
210 ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE,
211 OID_SIZE( OID_NS_CERT_TYPE ),
212 buf, 4 );
213 if( ret != 0 )
214 return( ret );
Paul Bakkere5eae762013-08-26 12:05:14 +0200215
216 return( 0 );
Paul Bakkerfde42702013-08-25 14:47:27 +0200217}
218
Paul Bakker9397dcb2013-09-06 09:55:26 +0200219void x509write_crt_init( x509write_cert *ctx )
220{
221 memset( ctx, 0, sizeof(x509write_cert) );
222
223 mpi_init( &ctx->serial );
224 ctx->version = X509_CRT_VERSION_3;
225}
226
227void x509write_crt_free( x509write_cert *ctx )
228{
Paul Bakker9397dcb2013-09-06 09:55:26 +0200229 mpi_free( &ctx->serial );
230
Paul Bakker5f45e622013-09-09 12:02:36 +0200231 asn1_free_named_data_list( &ctx->subject );
232 asn1_free_named_data_list( &ctx->issuer );
233 asn1_free_named_data_list( &ctx->extensions );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200234
Paul Bakkercd358032013-09-09 12:08:11 +0200235 memset( ctx, 0, sizeof(x509write_csr) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200236}
237
238void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg )
239{
240 ctx->md_alg = md_alg;
241}
242
Manuel Pégourié-Gonnardf38e71a2013-09-12 05:21:54 +0200243void x509write_crt_set_subject_key( x509write_cert *ctx, pk_context *key )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200244{
Manuel Pégourié-Gonnard53c64252013-09-12 05:39:46 +0200245 ctx->subject_key = key;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200246}
247
Manuel Pégourié-Gonnardf38e71a2013-09-12 05:21:54 +0200248void x509write_crt_set_issuer_key( x509write_cert *ctx, pk_context *key )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200249{
Manuel Pégourié-Gonnard53c64252013-09-12 05:39:46 +0200250 ctx->issuer_key = key;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200251}
252
253int x509write_crt_set_subject_name( x509write_cert *ctx, char *subject_name )
254{
255 return x509write_string_to_names( &ctx->subject, subject_name );
256}
257
258int x509write_crt_set_issuer_name( x509write_cert *ctx, char *issuer_name )
259{
260 return x509write_string_to_names( &ctx->issuer, issuer_name );
261}
262
263int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial )
264{
265 int ret;
266
267 if( ( ret = mpi_copy( &ctx->serial, serial ) ) != 0 )
268 return( ret );
269
270 return( 0 );
271}
272
273int x509write_crt_set_validity( x509write_cert *ctx, char *not_before,
274 char *not_after )
275{
276 if( strlen(not_before) != X509_RFC5280_UTC_TIME_LEN - 1 ||
277 strlen(not_after) != X509_RFC5280_UTC_TIME_LEN - 1 )
278 {
279 return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
280 }
281 strncpy( ctx->not_before, not_before, X509_RFC5280_UTC_TIME_LEN );
282 strncpy( ctx->not_after , not_after , X509_RFC5280_UTC_TIME_LEN );
283 ctx->not_before[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
284 ctx->not_after[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
285
286 return( 0 );
287}
288
Paul Bakker15162a02013-09-06 19:27:21 +0200289int x509write_crt_set_extension( x509write_cert *ctx,
290 const char *oid, size_t oid_len,
291 int critical,
292 const unsigned char *val, size_t val_len )
293{
294 return x509_set_extension( &ctx->extensions, oid, oid_len,
295 critical, val, val_len );
296}
297
298int x509write_crt_set_basic_constraints( x509write_cert *ctx,
299 int is_ca, int max_pathlen )
300{
301 int ret;
302 unsigned char buf[9];
303 unsigned char *c = buf + sizeof(buf);
304 size_t len = 0;
305
306 memset( buf, 0, sizeof(buf) );
307
308 if( is_ca && max_pathlen > 127 )
309 return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
310
311 if( is_ca )
312 {
313 if( max_pathlen >= 0 )
314 {
315 ASN1_CHK_ADD( len, asn1_write_int( &c, buf, max_pathlen ) );
316 }
317 ASN1_CHK_ADD( len, asn1_write_bool( &c, buf, 1 ) );
318 }
319
320 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
321 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
322
323 return x509write_crt_set_extension( ctx, OID_BASIC_CONSTRAINTS,
324 OID_SIZE( OID_BASIC_CONSTRAINTS ),
325 0, buf + sizeof(buf) - len, len );
326}
327
328int x509write_crt_set_subject_key_identifier( x509write_cert *ctx )
329{
330 int ret;
331 unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
332 unsigned char *c = buf + sizeof(buf);
333 size_t len = 0;
334
335 memset( buf, 0, sizeof(buf));
Paul Bakkerc7bb02b2013-09-15 14:54:56 +0200336 ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, ctx->subject_key ) );
Paul Bakker15162a02013-09-06 19:27:21 +0200337
338 sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
339 c = buf + sizeof(buf) - 20;
340 len = 20;
341
342 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
343 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_OCTET_STRING ) );
344
345 return x509write_crt_set_extension( ctx, OID_SUBJECT_KEY_IDENTIFIER,
346 OID_SIZE( OID_SUBJECT_KEY_IDENTIFIER ),
347 0, buf + sizeof(buf) - len, len );
348}
349
350int x509write_crt_set_authority_key_identifier( x509write_cert *ctx )
351{
352 int ret;
353 unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
354 unsigned char *c = buf + sizeof(buf);
355 size_t len = 0;
356
357 memset( buf, 0, sizeof(buf));
Paul Bakkerc7bb02b2013-09-15 14:54:56 +0200358 ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, ctx->issuer_key ) );
Paul Bakker15162a02013-09-06 19:27:21 +0200359
360 sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
361 c = buf + sizeof(buf) - 20;
362 len = 20;
363
364 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
365 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONTEXT_SPECIFIC | 0 ) );
366
367 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
368 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
369
370 return x509write_crt_set_extension( ctx, OID_AUTHORITY_KEY_IDENTIFIER,
371 OID_SIZE( OID_AUTHORITY_KEY_IDENTIFIER ),
372 0, buf + sizeof(buf) - len, len );
373}
374
Paul Bakker52be08c2013-09-09 12:37:54 +0200375int x509write_crt_set_key_usage( x509write_cert *ctx, unsigned char key_usage )
376{
377 unsigned char buf[4];
378 unsigned char *c;
379 int ret;
380
381 c = buf + 4;
382
383 if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
384 return( ret );
385
386 ret = x509write_crt_set_extension( ctx, OID_KEY_USAGE,
387 OID_SIZE( OID_KEY_USAGE ),
388 1, buf, 4 );
389 if( ret != 0 )
390 return( ret );
391
392 return( 0 );
393}
394
395int x509write_crt_set_ns_cert_type( x509write_cert *ctx,
396 unsigned char ns_cert_type )
397{
398 unsigned char buf[4];
399 unsigned char *c;
400 int ret;
401
402 c = buf + 4;
403
404 if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
405 return( ret );
406
407 ret = x509write_crt_set_extension( ctx, OID_NS_CERT_TYPE,
408 OID_SIZE( OID_NS_CERT_TYPE ),
409 0, buf, 4 );
410 if( ret != 0 )
411 return( ret );
412
413 return( 0 );
414}
415
Paul Bakker9397dcb2013-09-06 09:55:26 +0200416/*
417 * RelativeDistinguishedName ::=
418 * SET OF AttributeTypeAndValue
419 *
420 * AttributeTypeAndValue ::= SEQUENCE {
421 * type AttributeType,
422 * value AttributeValue }
423 *
424 * AttributeType ::= OBJECT IDENTIFIER
425 *
426 * AttributeValue ::= ANY DEFINED BY AttributeType
427 */
Paul Bakker5f45e622013-09-09 12:02:36 +0200428static int x509_write_name( unsigned char **p, unsigned char *start,
429 const char *oid, size_t oid_len,
430 const unsigned char *name, size_t name_len )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000431{
432 int ret;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000433 size_t len = 0;
434
Paul Bakker05888152012-02-16 10:26:57 +0000435 // Write PrintableString for all except OID_PKCS9_EMAIL
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000436 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200437 if( OID_SIZE( OID_PKCS9_EMAIL ) == oid_len &&
438 memcmp( oid, OID_PKCS9_EMAIL, oid_len ) == 0 )
Paul Bakker05888152012-02-16 10:26:57 +0000439 {
Paul Bakker5f45e622013-09-09 12:02:36 +0200440 ASN1_CHK_ADD( len, asn1_write_ia5_string( p, start,
441 (const char *) name,
442 name_len ) );
Paul Bakker05888152012-02-16 10:26:57 +0000443 }
444 else
Paul Bakker5f45e622013-09-09 12:02:36 +0200445 {
446 ASN1_CHK_ADD( len, asn1_write_printable_string( p, start,
447 (const char *) name,
448 name_len ) );
449 }
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000450
451 // Write OID
452 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200453 ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000454
Paul Bakker5f45e622013-09-09 12:02:36 +0200455 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000456 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
457
458 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
459 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) );
460
461 return( len );
462}
463
Paul Bakker9397dcb2013-09-06 09:55:26 +0200464static int x509_write_names( unsigned char **p, unsigned char *start,
Paul Bakker5f45e622013-09-09 12:02:36 +0200465 asn1_named_data *first )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200466{
467 int ret;
468 size_t len = 0;
Paul Bakker5f45e622013-09-09 12:02:36 +0200469 asn1_named_data *cur = first;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200470
471 while( cur != NULL )
472 {
Paul Bakker5f45e622013-09-09 12:02:36 +0200473 ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p,
474 cur->oid.len,
475 cur->val.p, cur->val.len ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200476 cur = cur->next;
477 }
478
479 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
480 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
481
482 return( len );
483}
484
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200485static int x509_write_sig( unsigned char **p, unsigned char *start,
Paul Bakker1c3853b2013-09-10 11:43:44 +0200486 const char *oid, size_t oid_len,
487 unsigned char *sig, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000488{
489 int ret;
490 size_t len = 0;
491
492 if( *p - start < (int) size + 1 )
493 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
494
495 len = size;
496 (*p) -= len;
497 memcpy( *p, sig, len );
498
499 *--(*p) = 0;
500 len += 1;
501
502 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
503 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
504
505 // Write OID
506 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200507 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid,
Manuel Pégourié-Gonnardedda9042013-09-12 02:17:54 +0200508 oid_len, 0 ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000509
510 return( len );
511}
512
Paul Bakker9397dcb2013-09-06 09:55:26 +0200513static int x509_write_time( unsigned char **p, unsigned char *start,
514 const char *time, size_t size )
515{
516 int ret;
517 size_t len = 0;
518
Paul Bakker9c208aa2013-09-08 15:44:31 +0200519 /*
520 * write ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
521 */
522 if( time[0] == '2' && time[1] == '0' && time [2] < '5' )
523 {
524 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
525 (const unsigned char *) time + 2,
526 size - 2 ) );
527 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
528 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_UTC_TIME ) );
529 }
530 else
531 {
532 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
533 (const unsigned char *) time,
534 size ) );
535 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
536 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_GENERALIZED_TIME ) );
537 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200538
539 return( len );
540}
541
Paul Bakker15162a02013-09-06 19:27:21 +0200542static int x509_write_extension( unsigned char **p, unsigned char *start,
543 asn1_named_data *ext )
544{
545 int ret;
546 size_t len = 0;
547
548 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->val.p + 1,
549 ext->val.len - 1 ) );
550 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->val.len - 1 ) );
551 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) );
552
553 if( ext->val.p[0] != 0 )
554 {
555 ASN1_CHK_ADD( len, asn1_write_bool( p, start, 1 ) );
556 }
557
558 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->oid.p,
559 ext->oid.len ) );
560 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->oid.len ) );
561 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) );
562
563 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
564 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
565
566 return( len );
567}
568
569/*
570 * Extension ::= SEQUENCE {
571 * extnID OBJECT IDENTIFIER,
572 * critical BOOLEAN DEFAULT FALSE,
573 * extnValue OCTET STRING
574 * -- contains the DER encoding of an ASN.1 value
575 * -- corresponding to the extension type identified
576 * -- by extnID
577 * }
578 */
579static int x509_write_extensions( unsigned char **p, unsigned char *start,
580 asn1_named_data *first )
581{
582 int ret;
583 size_t len = 0;
584 asn1_named_data *cur_ext = first;
585
586 while( cur_ext != NULL )
587 {
588 ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
589 cur_ext = cur_ext->next;
590 }
591
592 return( len );
593}
594
Manuel Pégourié-Gonnardee731792013-09-11 22:48:40 +0200595int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size,
596 int (*f_rng)(void *, unsigned char *, size_t),
597 void *p_rng )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000598{
599 int ret;
Paul Bakkerc70b9822013-04-07 22:00:46 +0200600 const char *sig_oid;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200601 size_t sig_oid_len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000602 unsigned char *c, *c2;
Paul Bakker3cac5e02012-02-16 14:08:06 +0000603 unsigned char hash[64];
604 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000605 unsigned char tmp_buf[2048];
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200606 size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000607 size_t len = 0;
Manuel Pégourié-Gonnard0088c692013-09-12 02:38:04 +0200608 pk_type_t pk_alg;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000609
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200610 /*
611 * Prepare data to be signed in tmp_buf
612 */
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200613 c = tmp_buf + sizeof( tmp_buf );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000614
Paul Bakker15162a02013-09-06 19:27:21 +0200615 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200616
Paul Bakkere5eae762013-08-26 12:05:14 +0200617 if( len )
Paul Bakkerfde42702013-08-25 14:47:27 +0200618 {
Paul Bakkere5eae762013-08-26 12:05:14 +0200619 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
620 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200621
Paul Bakkere5eae762013-08-26 12:05:14 +0200622 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
623 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200624
Paul Bakker5f45e622013-09-09 12:02:36 +0200625 ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ,
626 OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200627
Paul Bakkere5eae762013-08-26 12:05:14 +0200628 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
629 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200630 }
631
Paul Bakkere5eae762013-08-26 12:05:14 +0200632 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000633 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) );
634
Paul Bakkerc7bb02b2013-09-15 14:54:56 +0200635 ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->key,
636 tmp_buf, c - tmp_buf ) );
Manuel Pégourié-Gonnard6dcf0bf2013-09-11 13:09:04 +0200637 c -= pub_len;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000638 len += pub_len;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000639
Paul Bakker9397dcb2013-09-06 09:55:26 +0200640 /*
641 * Subject ::= Name
642 */
643 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000644
Paul Bakker8eabfc12013-08-25 10:18:25 +0200645 /*
646 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
647 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000648 ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
649
650 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
651 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200652
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200653 /*
654 * Prepare signature
655 */
Paul Bakker8eabfc12013-08-25 10:18:25 +0200656 md( md_info_from_type( ctx->md_alg ), c, len, hash );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000657
Manuel Pégourié-Gonnard0088c692013-09-12 02:38:04 +0200658 pk_alg = pk_get_type( ctx->key );
659 if( pk_alg == POLARSSL_PK_ECKEY )
660 pk_alg = POLARSSL_PK_ECDSA;
661
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200662 if( ( ret = pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,
Manuel Pégourié-Gonnardee731792013-09-11 22:48:40 +0200663 f_rng, p_rng ) ) != 0 ||
Manuel Pégourié-Gonnard0088c692013-09-12 02:38:04 +0200664 ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200665 &sig_oid, &sig_oid_len ) ) != 0 )
666 {
667 return( ret );
668 }
Manuel Pégourié-Gonnard5353a032013-09-11 12:14:26 +0200669
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200670 /*
671 * Write data to output buffer
672 */
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200673 c2 = buf + size;
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200674 ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf,
675 sig_oid, sig_oid_len, sig, sig_len ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200676
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000677 c2 -= len;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200678 memcpy( c2, c, len );
679
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200680 len += sig_and_oid_len;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000681 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
682 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
683
684 return( len );
685}
686
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200687int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size,
688 int (*f_rng)(void *, unsigned char *, size_t),
689 void *p_rng )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200690{
691 int ret;
692 const char *sig_oid;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200693 size_t sig_oid_len = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200694 unsigned char *c, *c2;
695 unsigned char hash[64];
696 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
697 unsigned char tmp_buf[2048];
Manuel Pégourié-Gonnard53c64252013-09-12 05:39:46 +0200698 size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200699 size_t len = 0;
Manuel Pégourié-Gonnard53c64252013-09-12 05:39:46 +0200700 pk_type_t pk_alg;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200701
Manuel Pégourié-Gonnard53c64252013-09-12 05:39:46 +0200702 /*
703 * Prepare data to be signed in tmp_buf
704 */
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200705 c = tmp_buf + sizeof( tmp_buf );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200706
Manuel Pégourié-Gonnard53c64252013-09-12 05:39:46 +0200707 /* Signature algorithm needed in TBS, and later for actual signature */
708 pk_alg = pk_get_type( ctx->issuer_key );
709 if( pk_alg == POLARSSL_PK_ECKEY )
710 pk_alg = POLARSSL_PK_ECDSA;
711
712 if( ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
713 &sig_oid, &sig_oid_len ) ) != 0 )
714 {
Paul Bakker9397dcb2013-09-06 09:55:26 +0200715 return( ret );
Manuel Pégourié-Gonnard53c64252013-09-12 05:39:46 +0200716 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200717
Paul Bakker15162a02013-09-06 19:27:21 +0200718 /*
719 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
720 */
721 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
722 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
723 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
724 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
725 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200726
727 /*
Manuel Pégourié-Gonnard6dcf0bf2013-09-11 13:09:04 +0200728 * SubjectPublicKeyInfo
Paul Bakker9397dcb2013-09-06 09:55:26 +0200729 */
Paul Bakkerc7bb02b2013-09-15 14:54:56 +0200730 ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->subject_key,
731 tmp_buf, c - tmp_buf ) );
Manuel Pégourié-Gonnard6dcf0bf2013-09-11 13:09:04 +0200732 c -= pub_len;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200733 len += pub_len;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200734
735 /*
736 * Subject ::= Name
737 */
738 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
739
740 /*
741 * Validity ::= SEQUENCE {
742 * notBefore Time,
743 * notAfter Time }
744 */
745 sub_len = 0;
746
747 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
748 X509_RFC5280_UTC_TIME_LEN ) );
749
750 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
751 X509_RFC5280_UTC_TIME_LEN ) );
752
753 len += sub_len;
754 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
755 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
756
757 /*
758 * Issuer ::= Name
759 */
760 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->issuer ) );
761
762 /*
763 * Signature ::= AlgorithmIdentifier
764 */
765 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf,
Manuel Pégourié-Gonnardedda9042013-09-12 02:17:54 +0200766 sig_oid, strlen( sig_oid ), 0 ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200767
768 /*
769 * Serial ::= INTEGER
770 */
771 ASN1_CHK_ADD( len, asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
772
773 /*
774 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
775 */
776 sub_len = 0;
777 ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) );
778 len += sub_len;
779 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
780 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) );
781
782 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
783 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
784
Manuel Pégourié-Gonnard53c64252013-09-12 05:39:46 +0200785 /*
786 * Make signature
787 */
Paul Bakker9397dcb2013-09-06 09:55:26 +0200788 md( md_info_from_type( ctx->md_alg ), c, len, hash );
789
Manuel Pégourié-Gonnard53c64252013-09-12 05:39:46 +0200790 if( ( ret = pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len,
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200791 f_rng, p_rng ) ) != 0 )
Manuel Pégourié-Gonnard53c64252013-09-12 05:39:46 +0200792 {
793 return( ret );
794 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200795
Manuel Pégourié-Gonnard53c64252013-09-12 05:39:46 +0200796 /*
797 * Write data to output buffer
798 */
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200799 c2 = buf + size;
Manuel Pégourié-Gonnard53c64252013-09-12 05:39:46 +0200800 ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf,
801 sig_oid, sig_oid_len, sig, sig_len ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200802
803 c2 -= len;
804 memcpy( c2, c, len );
805
Manuel Pégourié-Gonnard53c64252013-09-12 05:39:46 +0200806 len += sig_and_oid_len;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200807 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
808 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
809
810 return( len );
811}
812
813#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
814#define PEM_END_CRT "-----END CERTIFICATE-----\n"
815
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200816#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n"
817#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n"
818
Paul Bakker135f1e92013-08-26 16:54:13 +0200819#if defined(POLARSSL_BASE64_C)
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200820static int x509write_pemify( const char *begin_str, const char *end_str,
821 const unsigned char *der_data, size_t der_len,
822 unsigned char *buf, size_t size )
Paul Bakker135f1e92013-08-26 16:54:13 +0200823{
824 int ret;
Paul Bakker135f1e92013-08-26 16:54:13 +0200825 unsigned char base_buf[4096];
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200826 unsigned char *c = base_buf, *p = buf;
827 size_t len = 0, olen = sizeof(base_buf);
Paul Bakker135f1e92013-08-26 16:54:13 +0200828
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200829 if( ( ret = base64_encode( base_buf, &olen, der_data, der_len ) ) != 0 )
Paul Bakker135f1e92013-08-26 16:54:13 +0200830 return( ret );
831
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200832 if( olen + strlen( begin_str ) + strlen( end_str ) +
Paul Bakker135f1e92013-08-26 16:54:13 +0200833 olen / 64 > size )
834 {
835 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
836 }
837
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200838 memcpy( p, begin_str, strlen( begin_str ) );
839 p += strlen( begin_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200840
841 while( olen )
842 {
843 len = ( olen > 64 ) ? 64 : olen;
844 memcpy( p, c, len );
845 olen -= len;
846 p += len;
847 c += len;
848 *p++ = '\n';
849 }
850
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200851 memcpy( p, end_str, strlen( end_str ) );
852 p += strlen( end_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200853
854 *p = '\0';
855
856 return( 0 );
857}
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200858
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200859int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size,
860 int (*f_rng)(void *, unsigned char *, size_t),
861 void *p_rng )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200862{
863 int ret;
864 unsigned char output_buf[4096];
865
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200866 if( ( ret = x509write_crt_der( crt, output_buf, sizeof(output_buf),
867 f_rng, p_rng ) ) < 0 )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200868 {
869 return( ret );
870 }
871
872 if( ( ret = x509write_pemify( PEM_BEGIN_CRT, PEM_END_CRT,
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200873 output_buf + sizeof(output_buf) - ret,
Paul Bakker9397dcb2013-09-06 09:55:26 +0200874 ret, buf, size ) ) != 0 )
875 {
876 return( ret );
877 }
878
879 return( 0 );
880}
881
Manuel Pégourié-Gonnardee731792013-09-11 22:48:40 +0200882int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size,
883 int (*f_rng)(void *, unsigned char *, size_t),
884 void *p_rng )
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200885{
886 int ret;
887 unsigned char output_buf[4096];
888
Manuel Pégourié-Gonnardee731792013-09-11 22:48:40 +0200889 if( ( ret = x509write_csr_der( ctx, output_buf, sizeof(output_buf),
890 f_rng, p_rng ) ) < 0 )
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200891 {
892 return( ret );
893 }
894
895 if( ( ret = x509write_pemify( PEM_BEGIN_CSR, PEM_END_CSR,
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200896 output_buf + sizeof(output_buf) - ret,
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200897 ret, buf, size ) ) != 0 )
898 {
899 return( ret );
900 }
901
902 return( 0 );
903}
Paul Bakker135f1e92013-08-26 16:54:13 +0200904#endif /* POLARSSL_BASE64_C */
905
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000906#endif