blob: 8966ecb737be8f3dd67b2a1e39d5fa1551de50b1 [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
26#include "polarssl/config.h"
27
28#if defined(POLARSSL_X509_WRITE_C)
29
30#include "polarssl/asn1write.h"
31#include "polarssl/x509write.h"
32#include "polarssl/x509.h"
Paul Bakkerc70b9822013-04-07 22:00:46 +020033#include "polarssl/md.h"
34#include "polarssl/oid.h"
Paul Bakkerbdb912d2012-02-13 23:11:30 +000035
Paul Bakker15162a02013-09-06 19:27:21 +020036#include "polarssl/sha1.h"
37
Paul Bakker135f1e92013-08-26 16:54:13 +020038#if defined(POLARSSL_BASE64_C)
39#include "polarssl/base64.h"
40#endif
41
Paul Bakker8eabfc12013-08-25 10:18:25 +020042#if defined(POLARSSL_MEMORY_C)
43#include "polarssl/memory.h"
44#else
45#include <stdlib.h>
46#define polarssl_malloc malloc
47#define polarssl_free free
48#endif
49
Paul Bakker9397dcb2013-09-06 09:55:26 +020050static int x509write_string_to_names( x509_req_name **head, char *name )
Paul Bakker8eabfc12013-08-25 10:18:25 +020051{
52 int ret = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +020053 char *s = name, *c = s;
Paul Bakker8eabfc12013-08-25 10:18:25 +020054 char *end = s + strlen( s );
55 char *oid = NULL;
56 int in_tag = 1;
Paul Bakker21307962013-08-25 10:33:27 +020057 x509_req_name *cur;
Paul Bakker8eabfc12013-08-25 10:18:25 +020058
Paul Bakker9397dcb2013-09-06 09:55:26 +020059 while( *head != NULL )
Paul Bakker8eabfc12013-08-25 10:18:25 +020060 {
Paul Bakker9397dcb2013-09-06 09:55:26 +020061 cur = *head;
62 *head = cur->next;
Paul Bakker8eabfc12013-08-25 10:18:25 +020063 polarssl_free( cur );
64 }
65
66 while( c <= end )
67 {
68 if( in_tag && *c == '=' )
69 {
70 if( memcmp( s, "CN", 2 ) == 0 && c - s == 2 )
71 oid = OID_AT_CN;
72 else if( memcmp( s, "C", 1 ) == 0 && c - s == 1 )
73 oid = OID_AT_COUNTRY;
74 else if( memcmp( s, "O", 1 ) == 0 && c - s == 1 )
75 oid = OID_AT_ORGANIZATION;
76 else if( memcmp( s, "L", 1 ) == 0 && c - s == 1 )
77 oid = OID_AT_LOCALITY;
78 else if( memcmp( s, "R", 1 ) == 0 && c - s == 1 )
79 oid = OID_PKCS9_EMAIL;
80 else if( memcmp( s, "OU", 2 ) == 0 && c - s == 2 )
81 oid = OID_AT_ORG_UNIT;
82 else if( memcmp( s, "ST", 2 ) == 0 && c - s == 2 )
83 oid = OID_AT_STATE;
84 else
85 {
Paul Bakker0e06c0f2013-08-25 11:21:30 +020086 ret = POLARSSL_ERR_X509WRITE_UNKNOWN_OID;
Paul Bakker8eabfc12013-08-25 10:18:25 +020087 goto exit;
88 }
89
90 s = c + 1;
91 in_tag = 0;
92 }
93
94 if( !in_tag && ( *c == ',' || c == end ) )
95 {
96 if( c - s > 127 )
97 {
Paul Bakker0e06c0f2013-08-25 11:21:30 +020098 ret = POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA;
Paul Bakker8eabfc12013-08-25 10:18:25 +020099 goto exit;
100 }
101
Paul Bakker21307962013-08-25 10:33:27 +0200102 cur = polarssl_malloc( sizeof(x509_req_name) );
Paul Bakker8eabfc12013-08-25 10:18:25 +0200103
104 if( cur == NULL )
105 {
Paul Bakker0e06c0f2013-08-25 11:21:30 +0200106 ret = POLARSSL_ERR_X509WRITE_MALLOC_FAILED;
Paul Bakker8eabfc12013-08-25 10:18:25 +0200107 goto exit;
108 }
109
110 memset( cur, 0, sizeof(x509_req_name) );
111
Paul Bakker9397dcb2013-09-06 09:55:26 +0200112 cur->next = *head;
113 *head = cur;
Paul Bakker21307962013-08-25 10:33:27 +0200114
Paul Bakker8eabfc12013-08-25 10:18:25 +0200115 strncpy( cur->oid, oid, strlen( oid ) );
116 strncpy( cur->name, s, c - s );
117
118 s = c + 1;
119 in_tag = 1;
120 }
121 c++;
122 }
123
124exit:
125
126 return( ret );
127}
128
Paul Bakker15162a02013-09-06 19:27:21 +0200129/*
130 * RSAPublicKey ::= SEQUENCE {
131 * modulus INTEGER, -- n
132 * publicExponent INTEGER -- e
133 * }
134 */
135static int x509_write_rsa_pubkey( unsigned char **p, unsigned char *start,
136 rsa_context *rsa )
137{
138 int ret;
139 size_t len = 0;
140
141 ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->E ) );
142 ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->N ) );
143
144 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
145 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
146
147 return( len );
148}
149
Paul Bakker9397dcb2013-09-06 09:55:26 +0200150void x509write_csr_init( x509_csr *ctx )
151{
152 memset( ctx, 0, sizeof(x509_csr) );
153}
154
155void x509write_csr_free( x509_csr *ctx )
156{
157 x509_req_name *cur;
158 asn1_named_data *cur_ext;
159
160 while( ( cur = ctx->subject ) != NULL )
161 {
162 ctx->subject = cur->next;
163 polarssl_free( cur );
164 }
165
166 while( ( cur_ext = ctx->extensions ) != NULL )
167 {
168 ctx->extensions = cur_ext->next;
169 asn1_free_named_data( cur_ext );
170 polarssl_free( cur_ext );
171 }
172
173 memset( ctx, 0, sizeof(x509_csr) );
174}
175
176void x509write_csr_set_md_alg( x509_csr *ctx, md_type_t md_alg )
177{
178 ctx->md_alg = md_alg;
179}
180
181void x509write_csr_set_rsa_key( x509_csr *ctx, rsa_context *rsa )
182{
183 ctx->rsa = rsa;
184}
185
186int x509write_csr_set_subject_name( x509_csr *ctx, char *subject_name )
187{
188 return x509write_string_to_names( &ctx->subject, subject_name );
189}
190
Paul Bakker15162a02013-09-06 19:27:21 +0200191/* The first byte of the value in the asn1_named_data structure is reserved
192 * to store the critical boolean for us
193 */
194static int x509_set_extension( asn1_named_data **head,
195 const char *oid, size_t oid_len,
196 int critical,
197 const unsigned char *val, size_t val_len )
Paul Bakkerfde42702013-08-25 14:47:27 +0200198{
Paul Bakkere5eae762013-08-26 12:05:14 +0200199 asn1_named_data *cur;
Paul Bakkere5eae762013-08-26 12:05:14 +0200200
Paul Bakker59ba59f2013-09-09 11:26:00 +0200201 if( ( cur = asn1_store_named_data( head, oid, oid_len,
202 NULL, val_len + 1 ) ) == NULL )
Paul Bakkere5eae762013-08-26 12:05:14 +0200203 {
Paul Bakker59ba59f2013-09-09 11:26:00 +0200204 return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
Paul Bakker1c0e5502013-08-26 13:41:01 +0200205 }
206
Paul Bakker15162a02013-09-06 19:27:21 +0200207 cur->val.p[0] = critical;
208 memcpy( cur->val.p + 1, val, val_len );
Paul Bakker1c0e5502013-08-26 13:41:01 +0200209
210 return( 0 );
211}
212
Paul Bakker15162a02013-09-06 19:27:21 +0200213int x509write_csr_set_extension( x509_csr *ctx,
214 const char *oid, size_t oid_len,
215 const unsigned char *val, size_t val_len )
216{
217 return x509_set_extension( &ctx->extensions, oid, oid_len,
218 0, val, val_len );
219}
220
Paul Bakker1c0e5502013-08-26 13:41:01 +0200221int x509write_csr_set_key_usage( x509_csr *ctx, unsigned char key_usage )
222{
223 unsigned char buf[4];
224 unsigned char *c;
225 int ret;
226
227 c = buf + 4;
228
Paul Bakker624d03a2013-08-26 14:12:57 +0200229 if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200230 return( ret );
231
232 ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE,
233 OID_SIZE( OID_KEY_USAGE ),
234 buf, 4 );
235 if( ret != 0 )
236 return( ret );
237
238 return( 0 );
239}
240
241int x509write_csr_set_ns_cert_type( x509_csr *ctx, unsigned char ns_cert_type )
242{
243 unsigned char buf[4];
244 unsigned char *c;
245 int ret;
246
247 c = buf + 4;
248
249 if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
250 return( ret );
251
252 ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE,
253 OID_SIZE( OID_NS_CERT_TYPE ),
254 buf, 4 );
255 if( ret != 0 )
256 return( ret );
Paul Bakkere5eae762013-08-26 12:05:14 +0200257
258 return( 0 );
Paul Bakkerfde42702013-08-25 14:47:27 +0200259}
260
Paul Bakker9397dcb2013-09-06 09:55:26 +0200261void x509write_crt_init( x509write_cert *ctx )
262{
263 memset( ctx, 0, sizeof(x509write_cert) );
264
265 mpi_init( &ctx->serial );
266 ctx->version = X509_CRT_VERSION_3;
267}
268
269void x509write_crt_free( x509write_cert *ctx )
270{
271 x509_req_name *cur;
272 asn1_named_data *cur_ext;
273
274 mpi_free( &ctx->serial );
275
276 while( ( cur = ctx->subject ) != NULL )
277 {
278 ctx->subject = cur->next;
279 polarssl_free( cur );
280 }
281
282 while( ( cur = ctx->issuer ) != NULL )
283 {
284 ctx->issuer = cur->next;
285 polarssl_free( cur );
286 }
287
288 while( ( cur_ext = ctx->extensions ) != NULL )
289 {
290 ctx->extensions = cur_ext->next;
291 asn1_free_named_data( cur_ext );
292 polarssl_free( cur_ext );
293 }
294
295 memset( ctx, 0, sizeof(x509_csr) );
296}
297
298void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg )
299{
300 ctx->md_alg = md_alg;
301}
302
303void x509write_crt_set_subject_key( x509write_cert *ctx, rsa_context *rsa )
304{
305 ctx->subject_key = rsa;
306}
307
308void x509write_crt_set_issuer_key( x509write_cert *ctx, rsa_context *rsa )
309{
310 ctx->issuer_key = rsa;
311}
312
313int x509write_crt_set_subject_name( x509write_cert *ctx, char *subject_name )
314{
315 return x509write_string_to_names( &ctx->subject, subject_name );
316}
317
318int x509write_crt_set_issuer_name( x509write_cert *ctx, char *issuer_name )
319{
320 return x509write_string_to_names( &ctx->issuer, issuer_name );
321}
322
323int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial )
324{
325 int ret;
326
327 if( ( ret = mpi_copy( &ctx->serial, serial ) ) != 0 )
328 return( ret );
329
330 return( 0 );
331}
332
333int x509write_crt_set_validity( x509write_cert *ctx, char *not_before,
334 char *not_after )
335{
336 if( strlen(not_before) != X509_RFC5280_UTC_TIME_LEN - 1 ||
337 strlen(not_after) != X509_RFC5280_UTC_TIME_LEN - 1 )
338 {
339 return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
340 }
341 strncpy( ctx->not_before, not_before, X509_RFC5280_UTC_TIME_LEN );
342 strncpy( ctx->not_after , not_after , X509_RFC5280_UTC_TIME_LEN );
343 ctx->not_before[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
344 ctx->not_after[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
345
346 return( 0 );
347}
348
Paul Bakker15162a02013-09-06 19:27:21 +0200349int x509write_crt_set_extension( x509write_cert *ctx,
350 const char *oid, size_t oid_len,
351 int critical,
352 const unsigned char *val, size_t val_len )
353{
354 return x509_set_extension( &ctx->extensions, oid, oid_len,
355 critical, val, val_len );
356}
357
358int x509write_crt_set_basic_constraints( x509write_cert *ctx,
359 int is_ca, int max_pathlen )
360{
361 int ret;
362 unsigned char buf[9];
363 unsigned char *c = buf + sizeof(buf);
364 size_t len = 0;
365
366 memset( buf, 0, sizeof(buf) );
367
368 if( is_ca && max_pathlen > 127 )
369 return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
370
371 if( is_ca )
372 {
373 if( max_pathlen >= 0 )
374 {
375 ASN1_CHK_ADD( len, asn1_write_int( &c, buf, max_pathlen ) );
376 }
377 ASN1_CHK_ADD( len, asn1_write_bool( &c, buf, 1 ) );
378 }
379
380 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
381 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
382
383 return x509write_crt_set_extension( ctx, OID_BASIC_CONSTRAINTS,
384 OID_SIZE( OID_BASIC_CONSTRAINTS ),
385 0, buf + sizeof(buf) - len, len );
386}
387
388int x509write_crt_set_subject_key_identifier( x509write_cert *ctx )
389{
390 int ret;
391 unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
392 unsigned char *c = buf + sizeof(buf);
393 size_t len = 0;
394
395 memset( buf, 0, sizeof(buf));
396 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, ctx->subject_key ) );
397
398 sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
399 c = buf + sizeof(buf) - 20;
400 len = 20;
401
402 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
403 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_OCTET_STRING ) );
404
405 return x509write_crt_set_extension( ctx, OID_SUBJECT_KEY_IDENTIFIER,
406 OID_SIZE( OID_SUBJECT_KEY_IDENTIFIER ),
407 0, buf + sizeof(buf) - len, len );
408}
409
410int x509write_crt_set_authority_key_identifier( x509write_cert *ctx )
411{
412 int ret;
413 unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
414 unsigned char *c = buf + sizeof(buf);
415 size_t len = 0;
416
417 memset( buf, 0, sizeof(buf));
418 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, ctx->issuer_key ) );
419
420 sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
421 c = buf + sizeof(buf) - 20;
422 len = 20;
423
424 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
425 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONTEXT_SPECIFIC | 0 ) );
426
427 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
428 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
429
430 return x509write_crt_set_extension( ctx, OID_AUTHORITY_KEY_IDENTIFIER,
431 OID_SIZE( OID_AUTHORITY_KEY_IDENTIFIER ),
432 0, buf + sizeof(buf) - len, len );
433}
434
Paul Bakker82e29452013-08-25 11:01:31 +0200435int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000436{
437 int ret;
438 unsigned char *c;
439 size_t len = 0;
440
441 c = buf + size - 1;
442
Paul Bakker15162a02013-09-06 19:27:21 +0200443 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, rsa ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000444
445 if( c - buf < 1 )
446 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
447
Paul Bakker8eabfc12013-08-25 10:18:25 +0200448 /*
449 * SubjectPublicKeyInfo ::= SEQUENCE {
450 * algorithm AlgorithmIdentifier,
451 * subjectPublicKey BIT STRING }
452 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000453 *--c = 0;
454 len += 1;
455
456 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
457 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) );
458
459 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf, OID_PKCS1_RSA ) );
460
461 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
462 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
463
464 return( len );
465}
466
Paul Bakker82e29452013-08-25 11:01:31 +0200467int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000468{
469 int ret;
470 unsigned char *c;
471 size_t len = 0;
472
473 c = buf + size - 1;
474
475 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) );
476 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) );
477 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) );
478 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) );
479 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) );
480 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) );
481 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) );
482 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) );
483 ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) );
484
485 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
486 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
487
488 // TODO: Make NON RSA Specific variant later on
489/* *--c = 0;
490 len += 1;
491
492 len += asn1_write_len( &c, len);
493 len += asn1_write_tag( &c, ASN1_BIT_STRING );
494
495 len += asn1_write_oid( &c, OID_PKCS1_RSA );
496
497 len += asn1_write_int( &c, 0 );
498
499 len += asn1_write_len( &c, len);
500 len += asn1_write_tag( &c, ASN1_CONSTRUCTED | ASN1_SEQUENCE );*/
501
502/* for(i = 0; i < len; ++i)
503 {
504 if (i % 16 == 0 ) printf("\n");
505 printf("%02x ", c[i]);
506 }
507 printf("\n");*/
508
509 return( len );
510}
511
Paul Bakker9397dcb2013-09-06 09:55:26 +0200512/*
513 * RelativeDistinguishedName ::=
514 * SET OF AttributeTypeAndValue
515 *
516 * AttributeTypeAndValue ::= SEQUENCE {
517 * type AttributeType,
518 * value AttributeValue }
519 *
520 * AttributeType ::= OBJECT IDENTIFIER
521 *
522 * AttributeValue ::= ANY DEFINED BY AttributeType
523 */
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200524static int x509_write_name( unsigned char **p, unsigned char *start, char *oid,
525 char *name )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000526{
527 int ret;
528 size_t string_len = 0;
529 size_t oid_len = 0;
530 size_t len = 0;
531
Paul Bakker05888152012-02-16 10:26:57 +0000532 // Write PrintableString for all except OID_PKCS9_EMAIL
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000533 //
Paul Bakker05888152012-02-16 10:26:57 +0000534 if( OID_SIZE( OID_PKCS9_EMAIL ) == strlen( oid ) &&
535 memcmp( oid, OID_PKCS9_EMAIL, strlen( oid ) ) == 0 )
536 {
537 ASN1_CHK_ADD( string_len, asn1_write_ia5_string( p, start, name ) );
538 }
539 else
540 ASN1_CHK_ADD( string_len, asn1_write_printable_string( p, start, name ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000541
542 // Write OID
543 //
544 ASN1_CHK_ADD( oid_len, asn1_write_oid( p, start, oid ) );
545
546 len = oid_len + string_len;
547 ASN1_CHK_ADD( len, asn1_write_len( p, start, oid_len + string_len ) );
548 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
549
550 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
551 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) );
552
553 return( len );
554}
555
Paul Bakker9397dcb2013-09-06 09:55:26 +0200556static int x509_write_names( unsigned char **p, unsigned char *start,
557 x509_req_name *first )
558{
559 int ret;
560 size_t len = 0;
561 x509_req_name *cur = first;
562
563 while( cur != NULL )
564 {
565 ASN1_CHK_ADD( len, x509_write_name( p, start, cur->oid, cur->name ) );
566 cur = cur->next;
567 }
568
569 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
570 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
571
572 return( len );
573}
574
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200575static int x509_write_sig( unsigned char **p, unsigned char *start,
576 const char *oid, unsigned char *sig, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000577{
578 int ret;
579 size_t len = 0;
580
581 if( *p - start < (int) size + 1 )
582 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
583
584 len = size;
585 (*p) -= len;
586 memcpy( *p, sig, len );
587
588 *--(*p) = 0;
589 len += 1;
590
591 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
592 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
593
594 // Write OID
595 //
596 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid ) );
597
598 return( len );
599}
600
Paul Bakker9397dcb2013-09-06 09:55:26 +0200601static int x509_write_time( unsigned char **p, unsigned char *start,
602 const char *time, size_t size )
603{
604 int ret;
605 size_t len = 0;
606
Paul Bakker9c208aa2013-09-08 15:44:31 +0200607 /*
608 * write ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
609 */
610 if( time[0] == '2' && time[1] == '0' && time [2] < '5' )
611 {
612 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
613 (const unsigned char *) time + 2,
614 size - 2 ) );
615 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
616 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_UTC_TIME ) );
617 }
618 else
619 {
620 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
621 (const unsigned char *) time,
622 size ) );
623 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
624 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_GENERALIZED_TIME ) );
625 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200626
627 return( len );
628}
629
Paul Bakker15162a02013-09-06 19:27:21 +0200630static int x509_write_extension( unsigned char **p, unsigned char *start,
631 asn1_named_data *ext )
632{
633 int ret;
634 size_t len = 0;
635
636 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->val.p + 1,
637 ext->val.len - 1 ) );
638 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->val.len - 1 ) );
639 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) );
640
641 if( ext->val.p[0] != 0 )
642 {
643 ASN1_CHK_ADD( len, asn1_write_bool( p, start, 1 ) );
644 }
645
646 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->oid.p,
647 ext->oid.len ) );
648 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->oid.len ) );
649 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) );
650
651 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
652 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
653
654 return( len );
655}
656
657/*
658 * Extension ::= SEQUENCE {
659 * extnID OBJECT IDENTIFIER,
660 * critical BOOLEAN DEFAULT FALSE,
661 * extnValue OCTET STRING
662 * -- contains the DER encoding of an ASN.1 value
663 * -- corresponding to the extension type identified
664 * -- by extnID
665 * }
666 */
667static int x509_write_extensions( unsigned char **p, unsigned char *start,
668 asn1_named_data *first )
669{
670 int ret;
671 size_t len = 0;
672 asn1_named_data *cur_ext = first;
673
674 while( cur_ext != NULL )
675 {
676 ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
677 cur_ext = cur_ext->next;
678 }
679
680 return( len );
681}
682
Paul Bakker82e29452013-08-25 11:01:31 +0200683int x509write_csr_der( x509_csr *ctx, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000684{
685 int ret;
Paul Bakkerc70b9822013-04-07 22:00:46 +0200686 const char *sig_oid;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000687 unsigned char *c, *c2;
Paul Bakker3cac5e02012-02-16 14:08:06 +0000688 unsigned char hash[64];
689 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000690 unsigned char tmp_buf[2048];
Paul Bakker9397dcb2013-09-06 09:55:26 +0200691 size_t pub_len = 0, sig_len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000692 size_t len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000693
694 c = tmp_buf + 2048 - 1;
695
Paul Bakker15162a02013-09-06 19:27:21 +0200696 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200697
Paul Bakkere5eae762013-08-26 12:05:14 +0200698 if( len )
Paul Bakkerfde42702013-08-25 14:47:27 +0200699 {
Paul Bakkere5eae762013-08-26 12:05:14 +0200700 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
701 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200702
Paul Bakkere5eae762013-08-26 12:05:14 +0200703 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
704 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200705
Paul Bakkere5eae762013-08-26 12:05:14 +0200706 ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200707
Paul Bakkere5eae762013-08-26 12:05:14 +0200708 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
709 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200710 }
711
Paul Bakkere5eae762013-08-26 12:05:14 +0200712 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000713 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) );
714
Paul Bakker8eabfc12013-08-25 10:18:25 +0200715 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->rsa->E ) );
716 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->rsa->N ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000717
718 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
719 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
720
721 if( c - tmp_buf < 1 )
722 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
723
Paul Bakker8eabfc12013-08-25 10:18:25 +0200724 /*
725 * AlgorithmIdentifier ::= SEQUENCE {
726 * algorithm OBJECT IDENTIFIER,
727 * parameters ANY DEFINED BY algorithm OPTIONAL }
728 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000729 *--c = 0;
730 pub_len += 1;
731
732 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
733 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_BIT_STRING ) );
734
735 ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf, OID_PKCS1_RSA ) );
736
737 len += pub_len;
738 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) );
739 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
740
Paul Bakker9397dcb2013-09-06 09:55:26 +0200741 /*
742 * Subject ::= Name
743 */
744 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000745
Paul Bakker8eabfc12013-08-25 10:18:25 +0200746 /*
747 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
748 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000749 ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
750
751 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
752 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200753
Paul Bakker8eabfc12013-08-25 10:18:25 +0200754 md( md_info_from_type( ctx->md_alg ), c, len, hash );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000755
Paul Bakker8eabfc12013-08-25 10:18:25 +0200756 rsa_pkcs1_sign( ctx->rsa, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000757
758 // Generate correct OID
759 //
Paul Bakker8eabfc12013-08-25 10:18:25 +0200760 ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000761
762 c2 = buf + size - 1;
Paul Bakker8eabfc12013-08-25 10:18:25 +0200763 ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig, ctx->rsa->len ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200764
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000765 c2 -= len;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200766 memcpy( c2, c, len );
767
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000768 len += sig_len;
769 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
770 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
771
772 return( len );
773}
774
Paul Bakker9397dcb2013-09-06 09:55:26 +0200775int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size )
776{
777 int ret;
778 const char *sig_oid;
779 unsigned char *c, *c2;
780 unsigned char hash[64];
781 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
782 unsigned char tmp_buf[2048];
783 size_t sub_len = 0, pub_len = 0, sig_len = 0;
784 size_t len = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200785
786 c = tmp_buf + 2048 - 1;
787
788 // Generate correct OID
789 //
790 ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid );
791 if( ret != 0 )
792 return( ret );
793
Paul Bakker15162a02013-09-06 19:27:21 +0200794 /*
795 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
796 */
797 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
798 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
799 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
800 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
801 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200802
803 /*
804 * SubjectPublicKeyInfo ::= SEQUENCE {
805 * algorithm AlgorithmIdentifier,
806 * subjectPublicKey BIT STRING }
807 */
808 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->subject_key->E ) );
809 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->subject_key->N ) );
810
811 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
812 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
813
814 if( c - tmp_buf < 1 )
815 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
816
817 *--c = 0;
818 pub_len += 1;
819
820 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
821 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_BIT_STRING ) );
822
823 ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf, OID_PKCS1_RSA ) );
824
825 len += pub_len;
826 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) );
827 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
828
829 /*
830 * Subject ::= Name
831 */
832 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
833
834 /*
835 * Validity ::= SEQUENCE {
836 * notBefore Time,
837 * notAfter Time }
838 */
839 sub_len = 0;
840
841 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
842 X509_RFC5280_UTC_TIME_LEN ) );
843
844 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
845 X509_RFC5280_UTC_TIME_LEN ) );
846
847 len += sub_len;
848 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
849 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
850
851 /*
852 * Issuer ::= Name
853 */
854 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->issuer ) );
855
856 /*
857 * Signature ::= AlgorithmIdentifier
858 */
859 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf,
860 sig_oid ) );
861
862 /*
863 * Serial ::= INTEGER
864 */
865 ASN1_CHK_ADD( len, asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
866
867 /*
868 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
869 */
870 sub_len = 0;
871 ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) );
872 len += sub_len;
873 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
874 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) );
875
876 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
877 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
878
879 md( md_info_from_type( ctx->md_alg ), c, len, hash );
880
881 rsa_pkcs1_sign( ctx->issuer_key, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig );
882
883 c2 = buf + size - 1;
884 ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig, ctx->issuer_key->len ) );
885
886 c2 -= len;
887 memcpy( c2, c, len );
888
889 len += sig_len;
890 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
891 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
892
893 return( len );
894}
895
896#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
897#define PEM_END_CRT "-----END CERTIFICATE-----\n"
898
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200899#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n"
900#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n"
901
902#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n"
903#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n"
904
905#define PEM_BEGIN_PRIVATE_KEY "-----BEGIN RSA PRIVATE KEY-----\n"
906#define PEM_END_PRIVATE_KEY "-----END RSA PRIVATE KEY-----\n"
Paul Bakker135f1e92013-08-26 16:54:13 +0200907
908#if defined(POLARSSL_BASE64_C)
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200909static int x509write_pemify( const char *begin_str, const char *end_str,
910 const unsigned char *der_data, size_t der_len,
911 unsigned char *buf, size_t size )
Paul Bakker135f1e92013-08-26 16:54:13 +0200912{
913 int ret;
Paul Bakker135f1e92013-08-26 16:54:13 +0200914 unsigned char base_buf[4096];
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200915 unsigned char *c = base_buf, *p = buf;
916 size_t len = 0, olen = sizeof(base_buf);
Paul Bakker135f1e92013-08-26 16:54:13 +0200917
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200918 if( ( ret = base64_encode( base_buf, &olen, der_data, der_len ) ) != 0 )
Paul Bakker135f1e92013-08-26 16:54:13 +0200919 return( ret );
920
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200921 if( olen + strlen( begin_str ) + strlen( end_str ) +
Paul Bakker135f1e92013-08-26 16:54:13 +0200922 olen / 64 > size )
923 {
924 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
925 }
926
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200927 memcpy( p, begin_str, strlen( begin_str ) );
928 p += strlen( begin_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200929
930 while( olen )
931 {
932 len = ( olen > 64 ) ? 64 : olen;
933 memcpy( p, c, len );
934 olen -= len;
935 p += len;
936 c += len;
937 *p++ = '\n';
938 }
939
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200940 memcpy( p, end_str, strlen( end_str ) );
941 p += strlen( end_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200942
943 *p = '\0';
944
945 return( 0 );
946}
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200947
Paul Bakker9397dcb2013-09-06 09:55:26 +0200948int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size )
949{
950 int ret;
951 unsigned char output_buf[4096];
952
953 if( ( ret = x509write_crt_der( crt, output_buf,
954 sizeof(output_buf) ) ) < 0 )
955 {
956 return( ret );
957 }
958
959 if( ( ret = x509write_pemify( PEM_BEGIN_CRT, PEM_END_CRT,
960 output_buf + sizeof(output_buf) - 1 - ret,
961 ret, buf, size ) ) != 0 )
962 {
963 return( ret );
964 }
965
966 return( 0 );
967}
968
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200969int x509write_pubkey_pem( rsa_context *rsa, unsigned char *buf, size_t size )
970{
971 int ret;
972 unsigned char output_buf[4096];
973
974 if( ( ret = x509write_pubkey_der( rsa, output_buf,
975 sizeof(output_buf) ) ) < 0 )
976 {
977 return( ret );
978 }
979
980 if( ( ret = x509write_pemify( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
981 output_buf + sizeof(output_buf) - 1 - ret,
982 ret, buf, size ) ) != 0 )
983 {
984 return( ret );
985 }
986
987 return( 0 );
988}
989
990int x509write_key_pem( rsa_context *rsa, unsigned char *buf, size_t size )
991{
992 int ret;
993 unsigned char output_buf[4096];
994
995 if( ( ret = x509write_key_der( rsa, output_buf,
996 sizeof(output_buf) ) ) < 0 )
997 {
998 return( ret );
999 }
1000
1001 if( ( ret = x509write_pemify( PEM_BEGIN_PRIVATE_KEY, PEM_END_PRIVATE_KEY,
1002 output_buf + sizeof(output_buf) - 1 - ret,
1003 ret, buf, size ) ) != 0 )
1004 {
1005 return( ret );
1006 }
1007
1008 return( 0 );
1009}
1010
1011int x509write_csr_pem( x509_csr *ctx, unsigned char *buf, size_t size )
1012{
1013 int ret;
1014 unsigned char output_buf[4096];
1015
1016 if( ( ret = x509write_csr_der( ctx, output_buf,
1017 sizeof(output_buf) ) ) < 0 )
1018 {
1019 return( ret );
1020 }
1021
1022 if( ( ret = x509write_pemify( PEM_BEGIN_CSR, PEM_END_CSR,
1023 output_buf + sizeof(output_buf) - 1 - ret,
1024 ret, buf, size ) ) != 0 )
1025 {
1026 return( ret );
1027 }
1028
1029 return( 0 );
1030}
Paul Bakker135f1e92013-08-26 16:54:13 +02001031#endif /* POLARSSL_BASE64_C */
1032
Paul Bakkerbdb912d2012-02-13 23:11:30 +00001033#endif