blob: c57e56a0b0fcfe4d80b7aca5a7019c7fd93bf3c3 [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 Bakkercd358032013-09-09 12:08:11 +0200137void x509write_csr_init( x509write_csr *ctx )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200138{
Paul Bakkercd358032013-09-09 12:08:11 +0200139 memset( ctx, 0, sizeof(x509write_csr) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200140}
141
Paul Bakkercd358032013-09-09 12:08:11 +0200142void x509write_csr_free( x509write_csr *ctx )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200143{
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
Paul Bakkercd358032013-09-09 12:08:11 +0200147 memset( ctx, 0, sizeof(x509write_csr) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200148}
149
Paul Bakkercd358032013-09-09 12:08:11 +0200150void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200151{
152 ctx->md_alg = md_alg;
153}
154
Paul Bakkercd358032013-09-09 12:08:11 +0200155void x509write_csr_set_rsa_key( x509write_csr *ctx, rsa_context *rsa )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200156{
157 ctx->rsa = rsa;
158}
159
Paul Bakkercd358032013-09-09 12:08:11 +0200160int x509write_csr_set_subject_name( x509write_csr *ctx, char *subject_name )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200161{
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 Bakkercd358032013-09-09 12:08:11 +0200187int x509write_csr_set_extension( x509write_csr *ctx,
Paul Bakker15162a02013-09-06 19:27:21 +0200188 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 Bakkercd358032013-09-09 12:08:11 +0200195int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200196{
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
Paul Bakkercd358032013-09-09 12:08:11 +0200215int x509write_csr_set_ns_cert_type( x509write_csr *ctx,
216 unsigned char ns_cert_type )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200217{
218 unsigned char buf[4];
219 unsigned char *c;
220 int ret;
221
222 c = buf + 4;
223
224 if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
225 return( ret );
226
227 ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE,
228 OID_SIZE( OID_NS_CERT_TYPE ),
229 buf, 4 );
230 if( ret != 0 )
231 return( ret );
Paul Bakkere5eae762013-08-26 12:05:14 +0200232
233 return( 0 );
Paul Bakkerfde42702013-08-25 14:47:27 +0200234}
235
Paul Bakker9397dcb2013-09-06 09:55:26 +0200236void x509write_crt_init( x509write_cert *ctx )
237{
238 memset( ctx, 0, sizeof(x509write_cert) );
239
240 mpi_init( &ctx->serial );
241 ctx->version = X509_CRT_VERSION_3;
242}
243
244void x509write_crt_free( x509write_cert *ctx )
245{
Paul Bakker9397dcb2013-09-06 09:55:26 +0200246 mpi_free( &ctx->serial );
247
Paul Bakker5f45e622013-09-09 12:02:36 +0200248 asn1_free_named_data_list( &ctx->subject );
249 asn1_free_named_data_list( &ctx->issuer );
250 asn1_free_named_data_list( &ctx->extensions );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200251
Paul Bakkercd358032013-09-09 12:08:11 +0200252 memset( ctx, 0, sizeof(x509write_csr) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200253}
254
255void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg )
256{
257 ctx->md_alg = md_alg;
258}
259
260void x509write_crt_set_subject_key( x509write_cert *ctx, rsa_context *rsa )
261{
262 ctx->subject_key = rsa;
263}
264
265void x509write_crt_set_issuer_key( x509write_cert *ctx, rsa_context *rsa )
266{
267 ctx->issuer_key = rsa;
268}
269
270int x509write_crt_set_subject_name( x509write_cert *ctx, char *subject_name )
271{
272 return x509write_string_to_names( &ctx->subject, subject_name );
273}
274
275int x509write_crt_set_issuer_name( x509write_cert *ctx, char *issuer_name )
276{
277 return x509write_string_to_names( &ctx->issuer, issuer_name );
278}
279
280int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial )
281{
282 int ret;
283
284 if( ( ret = mpi_copy( &ctx->serial, serial ) ) != 0 )
285 return( ret );
286
287 return( 0 );
288}
289
290int x509write_crt_set_validity( x509write_cert *ctx, char *not_before,
291 char *not_after )
292{
293 if( strlen(not_before) != X509_RFC5280_UTC_TIME_LEN - 1 ||
294 strlen(not_after) != X509_RFC5280_UTC_TIME_LEN - 1 )
295 {
296 return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
297 }
298 strncpy( ctx->not_before, not_before, X509_RFC5280_UTC_TIME_LEN );
299 strncpy( ctx->not_after , not_after , X509_RFC5280_UTC_TIME_LEN );
300 ctx->not_before[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
301 ctx->not_after[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
302
303 return( 0 );
304}
305
Paul Bakker15162a02013-09-06 19:27:21 +0200306int x509write_crt_set_extension( x509write_cert *ctx,
307 const char *oid, size_t oid_len,
308 int critical,
309 const unsigned char *val, size_t val_len )
310{
311 return x509_set_extension( &ctx->extensions, oid, oid_len,
312 critical, val, val_len );
313}
314
315int x509write_crt_set_basic_constraints( x509write_cert *ctx,
316 int is_ca, int max_pathlen )
317{
318 int ret;
319 unsigned char buf[9];
320 unsigned char *c = buf + sizeof(buf);
321 size_t len = 0;
322
323 memset( buf, 0, sizeof(buf) );
324
325 if( is_ca && max_pathlen > 127 )
326 return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
327
328 if( is_ca )
329 {
330 if( max_pathlen >= 0 )
331 {
332 ASN1_CHK_ADD( len, asn1_write_int( &c, buf, max_pathlen ) );
333 }
334 ASN1_CHK_ADD( len, asn1_write_bool( &c, buf, 1 ) );
335 }
336
337 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
338 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
339
340 return x509write_crt_set_extension( ctx, OID_BASIC_CONSTRAINTS,
341 OID_SIZE( OID_BASIC_CONSTRAINTS ),
342 0, buf + sizeof(buf) - len, len );
343}
344
345int x509write_crt_set_subject_key_identifier( x509write_cert *ctx )
346{
347 int ret;
348 unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
349 unsigned char *c = buf + sizeof(buf);
350 size_t len = 0;
351
352 memset( buf, 0, sizeof(buf));
353 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, ctx->subject_key ) );
354
355 sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
356 c = buf + sizeof(buf) - 20;
357 len = 20;
358
359 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
360 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_OCTET_STRING ) );
361
362 return x509write_crt_set_extension( ctx, OID_SUBJECT_KEY_IDENTIFIER,
363 OID_SIZE( OID_SUBJECT_KEY_IDENTIFIER ),
364 0, buf + sizeof(buf) - len, len );
365}
366
367int x509write_crt_set_authority_key_identifier( x509write_cert *ctx )
368{
369 int ret;
370 unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
371 unsigned char *c = buf + sizeof(buf);
372 size_t len = 0;
373
374 memset( buf, 0, sizeof(buf));
375 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, ctx->issuer_key ) );
376
377 sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
378 c = buf + sizeof(buf) - 20;
379 len = 20;
380
381 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
382 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONTEXT_SPECIFIC | 0 ) );
383
384 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
385 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
386
387 return x509write_crt_set_extension( ctx, OID_AUTHORITY_KEY_IDENTIFIER,
388 OID_SIZE( OID_AUTHORITY_KEY_IDENTIFIER ),
389 0, buf + sizeof(buf) - len, len );
390}
391
Paul Bakker52be08c2013-09-09 12:37:54 +0200392int x509write_crt_set_key_usage( x509write_cert *ctx, unsigned char key_usage )
393{
394 unsigned char buf[4];
395 unsigned char *c;
396 int ret;
397
398 c = buf + 4;
399
400 if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
401 return( ret );
402
403 ret = x509write_crt_set_extension( ctx, OID_KEY_USAGE,
404 OID_SIZE( OID_KEY_USAGE ),
405 1, buf, 4 );
406 if( ret != 0 )
407 return( ret );
408
409 return( 0 );
410}
411
412int x509write_crt_set_ns_cert_type( x509write_cert *ctx,
413 unsigned char ns_cert_type )
414{
415 unsigned char buf[4];
416 unsigned char *c;
417 int ret;
418
419 c = buf + 4;
420
421 if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
422 return( ret );
423
424 ret = x509write_crt_set_extension( ctx, OID_NS_CERT_TYPE,
425 OID_SIZE( OID_NS_CERT_TYPE ),
426 0, buf, 4 );
427 if( ret != 0 )
428 return( ret );
429
430 return( 0 );
431}
432
Paul Bakker82e29452013-08-25 11:01:31 +0200433int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000434{
435 int ret;
436 unsigned char *c;
437 size_t len = 0;
438
439 c = buf + size - 1;
440
Paul Bakker15162a02013-09-06 19:27:21 +0200441 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, rsa ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000442
443 if( c - buf < 1 )
444 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
445
Paul Bakker8eabfc12013-08-25 10:18:25 +0200446 /*
447 * SubjectPublicKeyInfo ::= SEQUENCE {
448 * algorithm AlgorithmIdentifier,
449 * subjectPublicKey BIT STRING }
450 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000451 *--c = 0;
452 len += 1;
453
454 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
455 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) );
456
Paul Bakker5f45e622013-09-09 12:02:36 +0200457 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf,
458 OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000459
460 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
461 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
462
463 return( len );
464}
465
Paul Bakker82e29452013-08-25 11:01:31 +0200466int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000467{
468 int ret;
469 unsigned char *c;
470 size_t len = 0;
471
472 c = buf + size - 1;
473
474 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) );
475 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) );
476 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) );
477 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) );
478 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) );
479 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) );
480 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) );
481 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) );
482 ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) );
483
484 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
485 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
486
487 // TODO: Make NON RSA Specific variant later on
488/* *--c = 0;
489 len += 1;
490
491 len += asn1_write_len( &c, len);
492 len += asn1_write_tag( &c, ASN1_BIT_STRING );
493
494 len += asn1_write_oid( &c, OID_PKCS1_RSA );
495
496 len += asn1_write_int( &c, 0 );
497
498 len += asn1_write_len( &c, len);
499 len += asn1_write_tag( &c, ASN1_CONSTRUCTED | ASN1_SEQUENCE );*/
500
501/* for(i = 0; i < len; ++i)
502 {
503 if (i % 16 == 0 ) printf("\n");
504 printf("%02x ", c[i]);
505 }
506 printf("\n");*/
507
508 return( len );
509}
510
Paul Bakker9397dcb2013-09-06 09:55:26 +0200511/*
512 * RelativeDistinguishedName ::=
513 * SET OF AttributeTypeAndValue
514 *
515 * AttributeTypeAndValue ::= SEQUENCE {
516 * type AttributeType,
517 * value AttributeValue }
518 *
519 * AttributeType ::= OBJECT IDENTIFIER
520 *
521 * AttributeValue ::= ANY DEFINED BY AttributeType
522 */
Paul Bakker5f45e622013-09-09 12:02:36 +0200523static int x509_write_name( unsigned char **p, unsigned char *start,
524 const char *oid, size_t oid_len,
525 const unsigned char *name, size_t name_len )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000526{
527 int ret;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000528 size_t len = 0;
529
Paul Bakker05888152012-02-16 10:26:57 +0000530 // Write PrintableString for all except OID_PKCS9_EMAIL
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000531 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200532 if( OID_SIZE( OID_PKCS9_EMAIL ) == oid_len &&
533 memcmp( oid, OID_PKCS9_EMAIL, oid_len ) == 0 )
Paul Bakker05888152012-02-16 10:26:57 +0000534 {
Paul Bakker5f45e622013-09-09 12:02:36 +0200535 ASN1_CHK_ADD( len, asn1_write_ia5_string( p, start,
536 (const char *) name,
537 name_len ) );
Paul Bakker05888152012-02-16 10:26:57 +0000538 }
539 else
Paul Bakker5f45e622013-09-09 12:02:36 +0200540 {
541 ASN1_CHK_ADD( len, asn1_write_printable_string( p, start,
542 (const char *) name,
543 name_len ) );
544 }
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000545
546 // Write OID
547 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200548 ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000549
Paul Bakker5f45e622013-09-09 12:02:36 +0200550 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000551 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
552
553 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
554 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) );
555
556 return( len );
557}
558
Paul Bakker9397dcb2013-09-06 09:55:26 +0200559static int x509_write_names( unsigned char **p, unsigned char *start,
Paul Bakker5f45e622013-09-09 12:02:36 +0200560 asn1_named_data *first )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200561{
562 int ret;
563 size_t len = 0;
Paul Bakker5f45e622013-09-09 12:02:36 +0200564 asn1_named_data *cur = first;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200565
566 while( cur != NULL )
567 {
Paul Bakker5f45e622013-09-09 12:02:36 +0200568 ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p,
569 cur->oid.len,
570 cur->val.p, cur->val.len ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200571 cur = cur->next;
572 }
573
574 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
575 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
576
577 return( len );
578}
579
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200580static int x509_write_sig( unsigned char **p, unsigned char *start,
581 const char *oid, unsigned char *sig, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000582{
583 int ret;
584 size_t len = 0;
585
586 if( *p - start < (int) size + 1 )
587 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
588
589 len = size;
590 (*p) -= len;
591 memcpy( *p, sig, len );
592
593 *--(*p) = 0;
594 len += 1;
595
596 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
597 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
598
599 // Write OID
600 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200601 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid,
602 strlen( oid ) ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000603
604 return( len );
605}
606
Paul Bakker9397dcb2013-09-06 09:55:26 +0200607static int x509_write_time( unsigned char **p, unsigned char *start,
608 const char *time, size_t size )
609{
610 int ret;
611 size_t len = 0;
612
Paul Bakker9c208aa2013-09-08 15:44:31 +0200613 /*
614 * write ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
615 */
616 if( time[0] == '2' && time[1] == '0' && time [2] < '5' )
617 {
618 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
619 (const unsigned char *) time + 2,
620 size - 2 ) );
621 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
622 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_UTC_TIME ) );
623 }
624 else
625 {
626 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
627 (const unsigned char *) time,
628 size ) );
629 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
630 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_GENERALIZED_TIME ) );
631 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200632
633 return( len );
634}
635
Paul Bakker15162a02013-09-06 19:27:21 +0200636static int x509_write_extension( unsigned char **p, unsigned char *start,
637 asn1_named_data *ext )
638{
639 int ret;
640 size_t len = 0;
641
642 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->val.p + 1,
643 ext->val.len - 1 ) );
644 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->val.len - 1 ) );
645 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) );
646
647 if( ext->val.p[0] != 0 )
648 {
649 ASN1_CHK_ADD( len, asn1_write_bool( p, start, 1 ) );
650 }
651
652 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->oid.p,
653 ext->oid.len ) );
654 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->oid.len ) );
655 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) );
656
657 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
658 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
659
660 return( len );
661}
662
663/*
664 * Extension ::= SEQUENCE {
665 * extnID OBJECT IDENTIFIER,
666 * critical BOOLEAN DEFAULT FALSE,
667 * extnValue OCTET STRING
668 * -- contains the DER encoding of an ASN.1 value
669 * -- corresponding to the extension type identified
670 * -- by extnID
671 * }
672 */
673static int x509_write_extensions( unsigned char **p, unsigned char *start,
674 asn1_named_data *first )
675{
676 int ret;
677 size_t len = 0;
678 asn1_named_data *cur_ext = first;
679
680 while( cur_ext != NULL )
681 {
682 ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
683 cur_ext = cur_ext->next;
684 }
685
686 return( len );
687}
688
Paul Bakkercd358032013-09-09 12:08:11 +0200689int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000690{
691 int ret;
Paul Bakkerc70b9822013-04-07 22:00:46 +0200692 const char *sig_oid;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000693 unsigned char *c, *c2;
Paul Bakker3cac5e02012-02-16 14:08:06 +0000694 unsigned char hash[64];
695 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000696 unsigned char tmp_buf[2048];
Paul Bakker9397dcb2013-09-06 09:55:26 +0200697 size_t pub_len = 0, sig_len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000698 size_t len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000699
700 c = tmp_buf + 2048 - 1;
701
Paul Bakker15162a02013-09-06 19:27:21 +0200702 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200703
Paul Bakkere5eae762013-08-26 12:05:14 +0200704 if( len )
Paul Bakkerfde42702013-08-25 14:47:27 +0200705 {
Paul Bakkere5eae762013-08-26 12:05:14 +0200706 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
707 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200708
Paul Bakkere5eae762013-08-26 12:05:14 +0200709 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
710 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200711
Paul Bakker5f45e622013-09-09 12:02:36 +0200712 ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ,
713 OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200714
Paul Bakkere5eae762013-08-26 12:05:14 +0200715 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
716 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200717 }
718
Paul Bakkere5eae762013-08-26 12:05:14 +0200719 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000720 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) );
721
Paul Bakker8eabfc12013-08-25 10:18:25 +0200722 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->rsa->E ) );
723 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->rsa->N ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000724
725 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
726 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
727
728 if( c - tmp_buf < 1 )
729 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
730
Paul Bakker8eabfc12013-08-25 10:18:25 +0200731 /*
732 * AlgorithmIdentifier ::= SEQUENCE {
733 * algorithm OBJECT IDENTIFIER,
734 * parameters ANY DEFINED BY algorithm OPTIONAL }
735 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000736 *--c = 0;
737 pub_len += 1;
738
739 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
740 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_BIT_STRING ) );
741
Paul Bakker5f45e622013-09-09 12:02:36 +0200742 ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf,
743 OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000744
745 len += pub_len;
746 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) );
747 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
748
Paul Bakker9397dcb2013-09-06 09:55:26 +0200749 /*
750 * Subject ::= Name
751 */
752 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000753
Paul Bakker8eabfc12013-08-25 10:18:25 +0200754 /*
755 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
756 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000757 ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
758
759 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
760 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200761
Paul Bakker8eabfc12013-08-25 10:18:25 +0200762 md( md_info_from_type( ctx->md_alg ), c, len, hash );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000763
Paul Bakker8eabfc12013-08-25 10:18:25 +0200764 rsa_pkcs1_sign( ctx->rsa, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000765
766 // Generate correct OID
767 //
Paul Bakker8eabfc12013-08-25 10:18:25 +0200768 ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000769
770 c2 = buf + size - 1;
Paul Bakker8eabfc12013-08-25 10:18:25 +0200771 ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig, ctx->rsa->len ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200772
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000773 c2 -= len;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200774 memcpy( c2, c, len );
775
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000776 len += sig_len;
777 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
778 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
779
780 return( len );
781}
782
Paul Bakker9397dcb2013-09-06 09:55:26 +0200783int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size )
784{
785 int ret;
786 const char *sig_oid;
787 unsigned char *c, *c2;
788 unsigned char hash[64];
789 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
790 unsigned char tmp_buf[2048];
791 size_t sub_len = 0, pub_len = 0, sig_len = 0;
792 size_t len = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200793
794 c = tmp_buf + 2048 - 1;
795
796 // Generate correct OID
797 //
798 ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid );
799 if( ret != 0 )
800 return( ret );
801
Paul Bakker15162a02013-09-06 19:27:21 +0200802 /*
803 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
804 */
805 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
806 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
807 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
808 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
809 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200810
811 /*
812 * SubjectPublicKeyInfo ::= SEQUENCE {
813 * algorithm AlgorithmIdentifier,
814 * subjectPublicKey BIT STRING }
815 */
816 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->subject_key->E ) );
817 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->subject_key->N ) );
818
819 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
820 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
821
822 if( c - tmp_buf < 1 )
823 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
824
825 *--c = 0;
826 pub_len += 1;
827
828 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
829 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_BIT_STRING ) );
830
Paul Bakker5f45e622013-09-09 12:02:36 +0200831 ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf,
832 OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200833
834 len += pub_len;
835 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) );
836 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
837
838 /*
839 * Subject ::= Name
840 */
841 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
842
843 /*
844 * Validity ::= SEQUENCE {
845 * notBefore Time,
846 * notAfter Time }
847 */
848 sub_len = 0;
849
850 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
851 X509_RFC5280_UTC_TIME_LEN ) );
852
853 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
854 X509_RFC5280_UTC_TIME_LEN ) );
855
856 len += sub_len;
857 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
858 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
859
860 /*
861 * Issuer ::= Name
862 */
863 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->issuer ) );
864
865 /*
866 * Signature ::= AlgorithmIdentifier
867 */
868 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf,
Paul Bakker5f45e622013-09-09 12:02:36 +0200869 sig_oid, strlen( sig_oid ) ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200870
871 /*
872 * Serial ::= INTEGER
873 */
874 ASN1_CHK_ADD( len, asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
875
876 /*
877 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
878 */
879 sub_len = 0;
880 ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) );
881 len += sub_len;
882 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
883 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) );
884
885 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
886 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
887
888 md( md_info_from_type( ctx->md_alg ), c, len, hash );
889
890 rsa_pkcs1_sign( ctx->issuer_key, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig );
891
892 c2 = buf + size - 1;
893 ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig, ctx->issuer_key->len ) );
894
895 c2 -= len;
896 memcpy( c2, c, len );
897
898 len += sig_len;
899 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
900 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
901
902 return( len );
903}
904
905#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
906#define PEM_END_CRT "-----END CERTIFICATE-----\n"
907
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200908#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n"
909#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n"
910
911#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n"
912#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n"
913
914#define PEM_BEGIN_PRIVATE_KEY "-----BEGIN RSA PRIVATE KEY-----\n"
915#define PEM_END_PRIVATE_KEY "-----END RSA PRIVATE KEY-----\n"
Paul Bakker135f1e92013-08-26 16:54:13 +0200916
917#if defined(POLARSSL_BASE64_C)
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200918static int x509write_pemify( const char *begin_str, const char *end_str,
919 const unsigned char *der_data, size_t der_len,
920 unsigned char *buf, size_t size )
Paul Bakker135f1e92013-08-26 16:54:13 +0200921{
922 int ret;
Paul Bakker135f1e92013-08-26 16:54:13 +0200923 unsigned char base_buf[4096];
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200924 unsigned char *c = base_buf, *p = buf;
925 size_t len = 0, olen = sizeof(base_buf);
Paul Bakker135f1e92013-08-26 16:54:13 +0200926
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200927 if( ( ret = base64_encode( base_buf, &olen, der_data, der_len ) ) != 0 )
Paul Bakker135f1e92013-08-26 16:54:13 +0200928 return( ret );
929
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200930 if( olen + strlen( begin_str ) + strlen( end_str ) +
Paul Bakker135f1e92013-08-26 16:54:13 +0200931 olen / 64 > size )
932 {
933 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
934 }
935
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200936 memcpy( p, begin_str, strlen( begin_str ) );
937 p += strlen( begin_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200938
939 while( olen )
940 {
941 len = ( olen > 64 ) ? 64 : olen;
942 memcpy( p, c, len );
943 olen -= len;
944 p += len;
945 c += len;
946 *p++ = '\n';
947 }
948
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200949 memcpy( p, end_str, strlen( end_str ) );
950 p += strlen( end_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200951
952 *p = '\0';
953
954 return( 0 );
955}
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200956
Paul Bakker9397dcb2013-09-06 09:55:26 +0200957int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size )
958{
959 int ret;
960 unsigned char output_buf[4096];
961
962 if( ( ret = x509write_crt_der( crt, output_buf,
963 sizeof(output_buf) ) ) < 0 )
964 {
965 return( ret );
966 }
967
968 if( ( ret = x509write_pemify( PEM_BEGIN_CRT, PEM_END_CRT,
969 output_buf + sizeof(output_buf) - 1 - ret,
970 ret, buf, size ) ) != 0 )
971 {
972 return( ret );
973 }
974
975 return( 0 );
976}
977
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200978int x509write_pubkey_pem( rsa_context *rsa, unsigned char *buf, size_t size )
979{
980 int ret;
981 unsigned char output_buf[4096];
982
983 if( ( ret = x509write_pubkey_der( rsa, output_buf,
984 sizeof(output_buf) ) ) < 0 )
985 {
986 return( ret );
987 }
988
989 if( ( ret = x509write_pemify( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
990 output_buf + sizeof(output_buf) - 1 - ret,
991 ret, buf, size ) ) != 0 )
992 {
993 return( ret );
994 }
995
996 return( 0 );
997}
998
999int x509write_key_pem( rsa_context *rsa, unsigned char *buf, size_t size )
1000{
1001 int ret;
1002 unsigned char output_buf[4096];
1003
1004 if( ( ret = x509write_key_der( rsa, output_buf,
1005 sizeof(output_buf) ) ) < 0 )
1006 {
1007 return( ret );
1008 }
1009
1010 if( ( ret = x509write_pemify( PEM_BEGIN_PRIVATE_KEY, PEM_END_PRIVATE_KEY,
1011 output_buf + sizeof(output_buf) - 1 - ret,
1012 ret, buf, size ) ) != 0 )
1013 {
1014 return( ret );
1015 }
1016
1017 return( 0 );
1018}
1019
Paul Bakkercd358032013-09-09 12:08:11 +02001020int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size )
Paul Bakkerf3df61a2013-08-26 17:22:23 +02001021{
1022 int ret;
1023 unsigned char output_buf[4096];
1024
1025 if( ( ret = x509write_csr_der( ctx, output_buf,
1026 sizeof(output_buf) ) ) < 0 )
1027 {
1028 return( ret );
1029 }
1030
1031 if( ( ret = x509write_pemify( PEM_BEGIN_CSR, PEM_END_CSR,
1032 output_buf + sizeof(output_buf) - 1 - ret,
1033 ret, buf, size ) ) != 0 )
1034 {
1035 return( ret );
1036 }
1037
1038 return( 0 );
1039}
Paul Bakker135f1e92013-08-26 16:54:13 +02001040#endif /* POLARSSL_BASE64_C */
1041
Paul Bakkerbdb912d2012-02-13 23:11:30 +00001042#endif