blob: 5d5d3de0087efed78390248afbe10ae07d11af97 [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 Bakker5f45e622013-09-09 12:02:36 +020050static int x509write_string_to_names( asn1_named_data **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 Bakker5f45e622013-09-09 12:02:36 +020057 asn1_named_data *cur;
Paul Bakker8eabfc12013-08-25 10:18:25 +020058
Paul Bakker5f45e622013-09-09 12:02:36 +020059 // Clear existing chain if present
60 //
Paul Bakker9397dcb2013-09-06 09:55:26 +020061 while( *head != NULL )
Paul Bakker8eabfc12013-08-25 10:18:25 +020062 {
Paul Bakker9397dcb2013-09-06 09:55:26 +020063 cur = *head;
64 *head = cur->next;
Paul Bakker8eabfc12013-08-25 10:18:25 +020065 polarssl_free( cur );
66 }
67
68 while( c <= end )
69 {
70 if( in_tag && *c == '=' )
71 {
72 if( memcmp( s, "CN", 2 ) == 0 && c - s == 2 )
73 oid = OID_AT_CN;
74 else if( memcmp( s, "C", 1 ) == 0 && c - s == 1 )
75 oid = OID_AT_COUNTRY;
76 else if( memcmp( s, "O", 1 ) == 0 && c - s == 1 )
77 oid = OID_AT_ORGANIZATION;
78 else if( memcmp( s, "L", 1 ) == 0 && c - s == 1 )
79 oid = OID_AT_LOCALITY;
80 else if( memcmp( s, "R", 1 ) == 0 && c - s == 1 )
81 oid = OID_PKCS9_EMAIL;
82 else if( memcmp( s, "OU", 2 ) == 0 && c - s == 2 )
83 oid = OID_AT_ORG_UNIT;
84 else if( memcmp( s, "ST", 2 ) == 0 && c - s == 2 )
85 oid = OID_AT_STATE;
86 else
87 {
Paul Bakker0e06c0f2013-08-25 11:21:30 +020088 ret = POLARSSL_ERR_X509WRITE_UNKNOWN_OID;
Paul Bakker8eabfc12013-08-25 10:18:25 +020089 goto exit;
90 }
91
92 s = c + 1;
93 in_tag = 0;
94 }
95
96 if( !in_tag && ( *c == ',' || c == end ) )
97 {
Paul Bakker5f45e622013-09-09 12:02:36 +020098 if( ( cur = asn1_store_named_data( head, oid, strlen( oid ),
99 (unsigned char *) s,
100 c - s ) ) == NULL )
Paul Bakker8eabfc12013-08-25 10:18:25 +0200101 {
Paul Bakker5f45e622013-09-09 12:02:36 +0200102 return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
Paul Bakker8eabfc12013-08-25 10:18:25 +0200103 }
104
Paul Bakker8eabfc12013-08-25 10:18:25 +0200105 s = c + 1;
106 in_tag = 1;
107 }
108 c++;
109 }
110
111exit:
112
113 return( ret );
114}
115
Paul Bakker15162a02013-09-06 19:27:21 +0200116/*
117 * RSAPublicKey ::= SEQUENCE {
118 * modulus INTEGER, -- n
119 * publicExponent INTEGER -- e
120 * }
121 */
122static int x509_write_rsa_pubkey( unsigned char **p, unsigned char *start,
123 rsa_context *rsa )
124{
125 int ret;
126 size_t len = 0;
127
128 ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->E ) );
129 ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->N ) );
130
131 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
132 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
133
134 return( len );
135}
136
Paul Bakker9397dcb2013-09-06 09:55:26 +0200137void x509write_csr_init( x509_csr *ctx )
138{
139 memset( ctx, 0, sizeof(x509_csr) );
140}
141
142void x509write_csr_free( x509_csr *ctx )
143{
Paul Bakker5f45e622013-09-09 12:02:36 +0200144 asn1_free_named_data_list( &ctx->subject );
145 asn1_free_named_data_list( &ctx->extensions );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200146
147 memset( ctx, 0, sizeof(x509_csr) );
148}
149
150void x509write_csr_set_md_alg( x509_csr *ctx, md_type_t md_alg )
151{
152 ctx->md_alg = md_alg;
153}
154
155void x509write_csr_set_rsa_key( x509_csr *ctx, rsa_context *rsa )
156{
157 ctx->rsa = rsa;
158}
159
160int x509write_csr_set_subject_name( x509_csr *ctx, char *subject_name )
161{
162 return x509write_string_to_names( &ctx->subject, subject_name );
163}
164
Paul Bakker15162a02013-09-06 19:27:21 +0200165/* The first byte of the value in the asn1_named_data structure is reserved
166 * to store the critical boolean for us
167 */
168static int x509_set_extension( asn1_named_data **head,
169 const char *oid, size_t oid_len,
170 int critical,
171 const unsigned char *val, size_t val_len )
Paul Bakkerfde42702013-08-25 14:47:27 +0200172{
Paul Bakkere5eae762013-08-26 12:05:14 +0200173 asn1_named_data *cur;
Paul Bakkere5eae762013-08-26 12:05:14 +0200174
Paul Bakker59ba59f2013-09-09 11:26:00 +0200175 if( ( cur = asn1_store_named_data( head, oid, oid_len,
176 NULL, val_len + 1 ) ) == NULL )
Paul Bakkere5eae762013-08-26 12:05:14 +0200177 {
Paul Bakker59ba59f2013-09-09 11:26:00 +0200178 return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
Paul Bakker1c0e5502013-08-26 13:41:01 +0200179 }
180
Paul Bakker15162a02013-09-06 19:27:21 +0200181 cur->val.p[0] = critical;
182 memcpy( cur->val.p + 1, val, val_len );
Paul Bakker1c0e5502013-08-26 13:41:01 +0200183
184 return( 0 );
185}
186
Paul Bakker15162a02013-09-06 19:27:21 +0200187int x509write_csr_set_extension( x509_csr *ctx,
188 const char *oid, size_t oid_len,
189 const unsigned char *val, size_t val_len )
190{
191 return x509_set_extension( &ctx->extensions, oid, oid_len,
192 0, val, val_len );
193}
194
Paul Bakker1c0e5502013-08-26 13:41:01 +0200195int x509write_csr_set_key_usage( x509_csr *ctx, unsigned char key_usage )
196{
197 unsigned char buf[4];
198 unsigned char *c;
199 int ret;
200
201 c = buf + 4;
202
Paul Bakker624d03a2013-08-26 14:12:57 +0200203 if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200204 return( ret );
205
206 ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE,
207 OID_SIZE( OID_KEY_USAGE ),
208 buf, 4 );
209 if( ret != 0 )
210 return( ret );
211
212 return( 0 );
213}
214
215int x509write_csr_set_ns_cert_type( x509_csr *ctx, unsigned char ns_cert_type )
216{
217 unsigned char buf[4];
218 unsigned char *c;
219 int ret;
220
221 c = buf + 4;
222
223 if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
224 return( ret );
225
226 ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE,
227 OID_SIZE( OID_NS_CERT_TYPE ),
228 buf, 4 );
229 if( ret != 0 )
230 return( ret );
Paul Bakkere5eae762013-08-26 12:05:14 +0200231
232 return( 0 );
Paul Bakkerfde42702013-08-25 14:47:27 +0200233}
234
Paul Bakker9397dcb2013-09-06 09:55:26 +0200235void x509write_crt_init( x509write_cert *ctx )
236{
237 memset( ctx, 0, sizeof(x509write_cert) );
238
239 mpi_init( &ctx->serial );
240 ctx->version = X509_CRT_VERSION_3;
241}
242
243void x509write_crt_free( x509write_cert *ctx )
244{
Paul Bakker9397dcb2013-09-06 09:55:26 +0200245 mpi_free( &ctx->serial );
246
Paul Bakker5f45e622013-09-09 12:02:36 +0200247 asn1_free_named_data_list( &ctx->subject );
248 asn1_free_named_data_list( &ctx->issuer );
249 asn1_free_named_data_list( &ctx->extensions );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200250
251 memset( ctx, 0, sizeof(x509_csr) );
252}
253
254void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg )
255{
256 ctx->md_alg = md_alg;
257}
258
259void x509write_crt_set_subject_key( x509write_cert *ctx, rsa_context *rsa )
260{
261 ctx->subject_key = rsa;
262}
263
264void x509write_crt_set_issuer_key( x509write_cert *ctx, rsa_context *rsa )
265{
266 ctx->issuer_key = rsa;
267}
268
269int x509write_crt_set_subject_name( x509write_cert *ctx, char *subject_name )
270{
271 return x509write_string_to_names( &ctx->subject, subject_name );
272}
273
274int x509write_crt_set_issuer_name( x509write_cert *ctx, char *issuer_name )
275{
276 return x509write_string_to_names( &ctx->issuer, issuer_name );
277}
278
279int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial )
280{
281 int ret;
282
283 if( ( ret = mpi_copy( &ctx->serial, serial ) ) != 0 )
284 return( ret );
285
286 return( 0 );
287}
288
289int x509write_crt_set_validity( x509write_cert *ctx, char *not_before,
290 char *not_after )
291{
292 if( strlen(not_before) != X509_RFC5280_UTC_TIME_LEN - 1 ||
293 strlen(not_after) != X509_RFC5280_UTC_TIME_LEN - 1 )
294 {
295 return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
296 }
297 strncpy( ctx->not_before, not_before, X509_RFC5280_UTC_TIME_LEN );
298 strncpy( ctx->not_after , not_after , X509_RFC5280_UTC_TIME_LEN );
299 ctx->not_before[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
300 ctx->not_after[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
301
302 return( 0 );
303}
304
Paul Bakker15162a02013-09-06 19:27:21 +0200305int x509write_crt_set_extension( x509write_cert *ctx,
306 const char *oid, size_t oid_len,
307 int critical,
308 const unsigned char *val, size_t val_len )
309{
310 return x509_set_extension( &ctx->extensions, oid, oid_len,
311 critical, val, val_len );
312}
313
314int x509write_crt_set_basic_constraints( x509write_cert *ctx,
315 int is_ca, int max_pathlen )
316{
317 int ret;
318 unsigned char buf[9];
319 unsigned char *c = buf + sizeof(buf);
320 size_t len = 0;
321
322 memset( buf, 0, sizeof(buf) );
323
324 if( is_ca && max_pathlen > 127 )
325 return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
326
327 if( is_ca )
328 {
329 if( max_pathlen >= 0 )
330 {
331 ASN1_CHK_ADD( len, asn1_write_int( &c, buf, max_pathlen ) );
332 }
333 ASN1_CHK_ADD( len, asn1_write_bool( &c, buf, 1 ) );
334 }
335
336 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
337 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
338
339 return x509write_crt_set_extension( ctx, OID_BASIC_CONSTRAINTS,
340 OID_SIZE( OID_BASIC_CONSTRAINTS ),
341 0, buf + sizeof(buf) - len, len );
342}
343
344int x509write_crt_set_subject_key_identifier( x509write_cert *ctx )
345{
346 int ret;
347 unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
348 unsigned char *c = buf + sizeof(buf);
349 size_t len = 0;
350
351 memset( buf, 0, sizeof(buf));
352 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, ctx->subject_key ) );
353
354 sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
355 c = buf + sizeof(buf) - 20;
356 len = 20;
357
358 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
359 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_OCTET_STRING ) );
360
361 return x509write_crt_set_extension( ctx, OID_SUBJECT_KEY_IDENTIFIER,
362 OID_SIZE( OID_SUBJECT_KEY_IDENTIFIER ),
363 0, buf + sizeof(buf) - len, len );
364}
365
366int x509write_crt_set_authority_key_identifier( x509write_cert *ctx )
367{
368 int ret;
369 unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
370 unsigned char *c = buf + sizeof(buf);
371 size_t len = 0;
372
373 memset( buf, 0, sizeof(buf));
374 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, ctx->issuer_key ) );
375
376 sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
377 c = buf + sizeof(buf) - 20;
378 len = 20;
379
380 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
381 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONTEXT_SPECIFIC | 0 ) );
382
383 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
384 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
385
386 return x509write_crt_set_extension( ctx, OID_AUTHORITY_KEY_IDENTIFIER,
387 OID_SIZE( OID_AUTHORITY_KEY_IDENTIFIER ),
388 0, buf + sizeof(buf) - len, len );
389}
390
Paul Bakker82e29452013-08-25 11:01:31 +0200391int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000392{
393 int ret;
394 unsigned char *c;
395 size_t len = 0;
396
397 c = buf + size - 1;
398
Paul Bakker15162a02013-09-06 19:27:21 +0200399 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, rsa ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000400
401 if( c - buf < 1 )
402 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
403
Paul Bakker8eabfc12013-08-25 10:18:25 +0200404 /*
405 * SubjectPublicKeyInfo ::= SEQUENCE {
406 * algorithm AlgorithmIdentifier,
407 * subjectPublicKey BIT STRING }
408 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000409 *--c = 0;
410 len += 1;
411
412 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
413 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) );
414
Paul Bakker5f45e622013-09-09 12:02:36 +0200415 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf,
416 OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000417
418 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
419 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
420
421 return( len );
422}
423
Paul Bakker82e29452013-08-25 11:01:31 +0200424int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000425{
426 int ret;
427 unsigned char *c;
428 size_t len = 0;
429
430 c = buf + size - 1;
431
432 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) );
433 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) );
434 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) );
435 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) );
436 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) );
437 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) );
438 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) );
439 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) );
440 ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) );
441
442 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
443 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
444
445 // TODO: Make NON RSA Specific variant later on
446/* *--c = 0;
447 len += 1;
448
449 len += asn1_write_len( &c, len);
450 len += asn1_write_tag( &c, ASN1_BIT_STRING );
451
452 len += asn1_write_oid( &c, OID_PKCS1_RSA );
453
454 len += asn1_write_int( &c, 0 );
455
456 len += asn1_write_len( &c, len);
457 len += asn1_write_tag( &c, ASN1_CONSTRUCTED | ASN1_SEQUENCE );*/
458
459/* for(i = 0; i < len; ++i)
460 {
461 if (i % 16 == 0 ) printf("\n");
462 printf("%02x ", c[i]);
463 }
464 printf("\n");*/
465
466 return( len );
467}
468
Paul Bakker9397dcb2013-09-06 09:55:26 +0200469/*
470 * RelativeDistinguishedName ::=
471 * SET OF AttributeTypeAndValue
472 *
473 * AttributeTypeAndValue ::= SEQUENCE {
474 * type AttributeType,
475 * value AttributeValue }
476 *
477 * AttributeType ::= OBJECT IDENTIFIER
478 *
479 * AttributeValue ::= ANY DEFINED BY AttributeType
480 */
Paul Bakker5f45e622013-09-09 12:02:36 +0200481static int x509_write_name( unsigned char **p, unsigned char *start,
482 const char *oid, size_t oid_len,
483 const unsigned char *name, size_t name_len )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000484{
485 int ret;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000486 size_t len = 0;
487
Paul Bakker05888152012-02-16 10:26:57 +0000488 // Write PrintableString for all except OID_PKCS9_EMAIL
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000489 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200490 if( OID_SIZE( OID_PKCS9_EMAIL ) == oid_len &&
491 memcmp( oid, OID_PKCS9_EMAIL, oid_len ) == 0 )
Paul Bakker05888152012-02-16 10:26:57 +0000492 {
Paul Bakker5f45e622013-09-09 12:02:36 +0200493 ASN1_CHK_ADD( len, asn1_write_ia5_string( p, start,
494 (const char *) name,
495 name_len ) );
Paul Bakker05888152012-02-16 10:26:57 +0000496 }
497 else
Paul Bakker5f45e622013-09-09 12:02:36 +0200498 {
499 ASN1_CHK_ADD( len, asn1_write_printable_string( p, start,
500 (const char *) name,
501 name_len ) );
502 }
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000503
504 // Write OID
505 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200506 ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000507
Paul Bakker5f45e622013-09-09 12:02:36 +0200508 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000509 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
510
511 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
512 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) );
513
514 return( len );
515}
516
Paul Bakker9397dcb2013-09-06 09:55:26 +0200517static int x509_write_names( unsigned char **p, unsigned char *start,
Paul Bakker5f45e622013-09-09 12:02:36 +0200518 asn1_named_data *first )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200519{
520 int ret;
521 size_t len = 0;
Paul Bakker5f45e622013-09-09 12:02:36 +0200522 asn1_named_data *cur = first;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200523
524 while( cur != NULL )
525 {
Paul Bakker5f45e622013-09-09 12:02:36 +0200526 ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p,
527 cur->oid.len,
528 cur->val.p, cur->val.len ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200529 cur = cur->next;
530 }
531
532 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
533 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
534
535 return( len );
536}
537
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200538static int x509_write_sig( unsigned char **p, unsigned char *start,
539 const char *oid, unsigned char *sig, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000540{
541 int ret;
542 size_t len = 0;
543
544 if( *p - start < (int) size + 1 )
545 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
546
547 len = size;
548 (*p) -= len;
549 memcpy( *p, sig, len );
550
551 *--(*p) = 0;
552 len += 1;
553
554 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
555 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
556
557 // Write OID
558 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200559 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid,
560 strlen( oid ) ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000561
562 return( len );
563}
564
Paul Bakker9397dcb2013-09-06 09:55:26 +0200565static int x509_write_time( unsigned char **p, unsigned char *start,
566 const char *time, size_t size )
567{
568 int ret;
569 size_t len = 0;
570
Paul Bakker9c208aa2013-09-08 15:44:31 +0200571 /*
572 * write ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
573 */
574 if( time[0] == '2' && time[1] == '0' && time [2] < '5' )
575 {
576 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
577 (const unsigned char *) time + 2,
578 size - 2 ) );
579 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
580 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_UTC_TIME ) );
581 }
582 else
583 {
584 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
585 (const unsigned char *) time,
586 size ) );
587 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
588 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_GENERALIZED_TIME ) );
589 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200590
591 return( len );
592}
593
Paul Bakker15162a02013-09-06 19:27:21 +0200594static int x509_write_extension( unsigned char **p, unsigned char *start,
595 asn1_named_data *ext )
596{
597 int ret;
598 size_t len = 0;
599
600 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->val.p + 1,
601 ext->val.len - 1 ) );
602 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->val.len - 1 ) );
603 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) );
604
605 if( ext->val.p[0] != 0 )
606 {
607 ASN1_CHK_ADD( len, asn1_write_bool( p, start, 1 ) );
608 }
609
610 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->oid.p,
611 ext->oid.len ) );
612 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->oid.len ) );
613 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) );
614
615 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
616 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
617
618 return( len );
619}
620
621/*
622 * Extension ::= SEQUENCE {
623 * extnID OBJECT IDENTIFIER,
624 * critical BOOLEAN DEFAULT FALSE,
625 * extnValue OCTET STRING
626 * -- contains the DER encoding of an ASN.1 value
627 * -- corresponding to the extension type identified
628 * -- by extnID
629 * }
630 */
631static int x509_write_extensions( unsigned char **p, unsigned char *start,
632 asn1_named_data *first )
633{
634 int ret;
635 size_t len = 0;
636 asn1_named_data *cur_ext = first;
637
638 while( cur_ext != NULL )
639 {
640 ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
641 cur_ext = cur_ext->next;
642 }
643
644 return( len );
645}
646
Paul Bakker82e29452013-08-25 11:01:31 +0200647int x509write_csr_der( x509_csr *ctx, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000648{
649 int ret;
Paul Bakkerc70b9822013-04-07 22:00:46 +0200650 const char *sig_oid;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000651 unsigned char *c, *c2;
Paul Bakker3cac5e02012-02-16 14:08:06 +0000652 unsigned char hash[64];
653 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000654 unsigned char tmp_buf[2048];
Paul Bakker9397dcb2013-09-06 09:55:26 +0200655 size_t pub_len = 0, sig_len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000656 size_t len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000657
658 c = tmp_buf + 2048 - 1;
659
Paul Bakker15162a02013-09-06 19:27:21 +0200660 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200661
Paul Bakkere5eae762013-08-26 12:05:14 +0200662 if( len )
Paul Bakkerfde42702013-08-25 14:47:27 +0200663 {
Paul Bakkere5eae762013-08-26 12:05:14 +0200664 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
665 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200666
Paul Bakkere5eae762013-08-26 12:05:14 +0200667 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
668 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200669
Paul Bakker5f45e622013-09-09 12:02:36 +0200670 ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ,
671 OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200672
Paul Bakkere5eae762013-08-26 12:05:14 +0200673 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
674 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200675 }
676
Paul Bakkere5eae762013-08-26 12:05:14 +0200677 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000678 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) );
679
Paul Bakker8eabfc12013-08-25 10:18:25 +0200680 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->rsa->E ) );
681 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->rsa->N ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000682
683 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
684 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
685
686 if( c - tmp_buf < 1 )
687 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
688
Paul Bakker8eabfc12013-08-25 10:18:25 +0200689 /*
690 * AlgorithmIdentifier ::= SEQUENCE {
691 * algorithm OBJECT IDENTIFIER,
692 * parameters ANY DEFINED BY algorithm OPTIONAL }
693 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000694 *--c = 0;
695 pub_len += 1;
696
697 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
698 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_BIT_STRING ) );
699
Paul Bakker5f45e622013-09-09 12:02:36 +0200700 ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf,
701 OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000702
703 len += pub_len;
704 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) );
705 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
706
Paul Bakker9397dcb2013-09-06 09:55:26 +0200707 /*
708 * Subject ::= Name
709 */
710 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000711
Paul Bakker8eabfc12013-08-25 10:18:25 +0200712 /*
713 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
714 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000715 ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
716
717 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
718 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200719
Paul Bakker8eabfc12013-08-25 10:18:25 +0200720 md( md_info_from_type( ctx->md_alg ), c, len, hash );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000721
Paul Bakker8eabfc12013-08-25 10:18:25 +0200722 rsa_pkcs1_sign( ctx->rsa, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000723
724 // Generate correct OID
725 //
Paul Bakker8eabfc12013-08-25 10:18:25 +0200726 ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000727
728 c2 = buf + size - 1;
Paul Bakker8eabfc12013-08-25 10:18:25 +0200729 ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig, ctx->rsa->len ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200730
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000731 c2 -= len;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200732 memcpy( c2, c, len );
733
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000734 len += sig_len;
735 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
736 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
737
738 return( len );
739}
740
Paul Bakker9397dcb2013-09-06 09:55:26 +0200741int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size )
742{
743 int ret;
744 const char *sig_oid;
745 unsigned char *c, *c2;
746 unsigned char hash[64];
747 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
748 unsigned char tmp_buf[2048];
749 size_t sub_len = 0, pub_len = 0, sig_len = 0;
750 size_t len = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200751
752 c = tmp_buf + 2048 - 1;
753
754 // Generate correct OID
755 //
756 ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid );
757 if( ret != 0 )
758 return( ret );
759
Paul Bakker15162a02013-09-06 19:27:21 +0200760 /*
761 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
762 */
763 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
764 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
765 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
766 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
767 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200768
769 /*
770 * SubjectPublicKeyInfo ::= SEQUENCE {
771 * algorithm AlgorithmIdentifier,
772 * subjectPublicKey BIT STRING }
773 */
774 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->subject_key->E ) );
775 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->subject_key->N ) );
776
777 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
778 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
779
780 if( c - tmp_buf < 1 )
781 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
782
783 *--c = 0;
784 pub_len += 1;
785
786 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
787 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_BIT_STRING ) );
788
Paul Bakker5f45e622013-09-09 12:02:36 +0200789 ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf,
790 OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200791
792 len += pub_len;
793 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) );
794 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
795
796 /*
797 * Subject ::= Name
798 */
799 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
800
801 /*
802 * Validity ::= SEQUENCE {
803 * notBefore Time,
804 * notAfter Time }
805 */
806 sub_len = 0;
807
808 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
809 X509_RFC5280_UTC_TIME_LEN ) );
810
811 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
812 X509_RFC5280_UTC_TIME_LEN ) );
813
814 len += sub_len;
815 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
816 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
817
818 /*
819 * Issuer ::= Name
820 */
821 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->issuer ) );
822
823 /*
824 * Signature ::= AlgorithmIdentifier
825 */
826 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf,
Paul Bakker5f45e622013-09-09 12:02:36 +0200827 sig_oid, strlen( sig_oid ) ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200828
829 /*
830 * Serial ::= INTEGER
831 */
832 ASN1_CHK_ADD( len, asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
833
834 /*
835 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
836 */
837 sub_len = 0;
838 ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) );
839 len += sub_len;
840 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
841 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) );
842
843 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
844 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
845
846 md( md_info_from_type( ctx->md_alg ), c, len, hash );
847
848 rsa_pkcs1_sign( ctx->issuer_key, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig );
849
850 c2 = buf + size - 1;
851 ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig, ctx->issuer_key->len ) );
852
853 c2 -= len;
854 memcpy( c2, c, len );
855
856 len += sig_len;
857 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
858 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
859
860 return( len );
861}
862
863#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
864#define PEM_END_CRT "-----END CERTIFICATE-----\n"
865
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200866#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n"
867#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n"
868
869#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n"
870#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n"
871
872#define PEM_BEGIN_PRIVATE_KEY "-----BEGIN RSA PRIVATE KEY-----\n"
873#define PEM_END_PRIVATE_KEY "-----END RSA PRIVATE KEY-----\n"
Paul Bakker135f1e92013-08-26 16:54:13 +0200874
875#if defined(POLARSSL_BASE64_C)
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200876static int x509write_pemify( const char *begin_str, const char *end_str,
877 const unsigned char *der_data, size_t der_len,
878 unsigned char *buf, size_t size )
Paul Bakker135f1e92013-08-26 16:54:13 +0200879{
880 int ret;
Paul Bakker135f1e92013-08-26 16:54:13 +0200881 unsigned char base_buf[4096];
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200882 unsigned char *c = base_buf, *p = buf;
883 size_t len = 0, olen = sizeof(base_buf);
Paul Bakker135f1e92013-08-26 16:54:13 +0200884
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200885 if( ( ret = base64_encode( base_buf, &olen, der_data, der_len ) ) != 0 )
Paul Bakker135f1e92013-08-26 16:54:13 +0200886 return( ret );
887
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200888 if( olen + strlen( begin_str ) + strlen( end_str ) +
Paul Bakker135f1e92013-08-26 16:54:13 +0200889 olen / 64 > size )
890 {
891 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
892 }
893
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200894 memcpy( p, begin_str, strlen( begin_str ) );
895 p += strlen( begin_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200896
897 while( olen )
898 {
899 len = ( olen > 64 ) ? 64 : olen;
900 memcpy( p, c, len );
901 olen -= len;
902 p += len;
903 c += len;
904 *p++ = '\n';
905 }
906
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200907 memcpy( p, end_str, strlen( end_str ) );
908 p += strlen( end_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200909
910 *p = '\0';
911
912 return( 0 );
913}
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200914
Paul Bakker9397dcb2013-09-06 09:55:26 +0200915int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size )
916{
917 int ret;
918 unsigned char output_buf[4096];
919
920 if( ( ret = x509write_crt_der( crt, output_buf,
921 sizeof(output_buf) ) ) < 0 )
922 {
923 return( ret );
924 }
925
926 if( ( ret = x509write_pemify( PEM_BEGIN_CRT, PEM_END_CRT,
927 output_buf + sizeof(output_buf) - 1 - ret,
928 ret, buf, size ) ) != 0 )
929 {
930 return( ret );
931 }
932
933 return( 0 );
934}
935
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200936int x509write_pubkey_pem( rsa_context *rsa, unsigned char *buf, size_t size )
937{
938 int ret;
939 unsigned char output_buf[4096];
940
941 if( ( ret = x509write_pubkey_der( rsa, output_buf,
942 sizeof(output_buf) ) ) < 0 )
943 {
944 return( ret );
945 }
946
947 if( ( ret = x509write_pemify( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
948 output_buf + sizeof(output_buf) - 1 - ret,
949 ret, buf, size ) ) != 0 )
950 {
951 return( ret );
952 }
953
954 return( 0 );
955}
956
957int x509write_key_pem( rsa_context *rsa, unsigned char *buf, size_t size )
958{
959 int ret;
960 unsigned char output_buf[4096];
961
962 if( ( ret = x509write_key_der( rsa, output_buf,
963 sizeof(output_buf) ) ) < 0 )
964 {
965 return( ret );
966 }
967
968 if( ( ret = x509write_pemify( PEM_BEGIN_PRIVATE_KEY, PEM_END_PRIVATE_KEY,
969 output_buf + sizeof(output_buf) - 1 - ret,
970 ret, buf, size ) ) != 0 )
971 {
972 return( ret );
973 }
974
975 return( 0 );
976}
977
978int x509write_csr_pem( x509_csr *ctx, unsigned char *buf, size_t size )
979{
980 int ret;
981 unsigned char output_buf[4096];
982
983 if( ( ret = x509write_csr_der( ctx, output_buf,
984 sizeof(output_buf) ) ) < 0 )
985 {
986 return( ret );
987 }
988
989 if( ( ret = x509write_pemify( PEM_BEGIN_CSR, PEM_END_CSR,
990 output_buf + sizeof(output_buf) - 1 - ret,
991 ret, buf, size ) ) != 0 )
992 {
993 return( ret );
994 }
995
996 return( 0 );
997}
Paul Bakker135f1e92013-08-26 16:54:13 +0200998#endif /* POLARSSL_BASE64_C */
999
Paul Bakkerbdb912d2012-02-13 23:11:30 +00001000#endif