blob: 818a83a0a81a7dda8678aba99bada72a25cae7df [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 Bakker82e29452013-08-25 11:01:31 +0200392int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000393{
394 int ret;
395 unsigned char *c;
396 size_t len = 0;
397
398 c = buf + size - 1;
399
Paul Bakker15162a02013-09-06 19:27:21 +0200400 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, rsa ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000401
402 if( c - buf < 1 )
403 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
404
Paul Bakker8eabfc12013-08-25 10:18:25 +0200405 /*
406 * SubjectPublicKeyInfo ::= SEQUENCE {
407 * algorithm AlgorithmIdentifier,
408 * subjectPublicKey BIT STRING }
409 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000410 *--c = 0;
411 len += 1;
412
413 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
414 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) );
415
Paul Bakker5f45e622013-09-09 12:02:36 +0200416 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf,
417 OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000418
419 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
420 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
421
422 return( len );
423}
424
Paul Bakker82e29452013-08-25 11:01:31 +0200425int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000426{
427 int ret;
428 unsigned char *c;
429 size_t len = 0;
430
431 c = buf + size - 1;
432
433 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) );
434 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) );
435 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) );
436 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) );
437 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) );
438 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) );
439 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) );
440 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) );
441 ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) );
442
443 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
444 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
445
446 // TODO: Make NON RSA Specific variant later on
447/* *--c = 0;
448 len += 1;
449
450 len += asn1_write_len( &c, len);
451 len += asn1_write_tag( &c, ASN1_BIT_STRING );
452
453 len += asn1_write_oid( &c, OID_PKCS1_RSA );
454
455 len += asn1_write_int( &c, 0 );
456
457 len += asn1_write_len( &c, len);
458 len += asn1_write_tag( &c, ASN1_CONSTRUCTED | ASN1_SEQUENCE );*/
459
460/* for(i = 0; i < len; ++i)
461 {
462 if (i % 16 == 0 ) printf("\n");
463 printf("%02x ", c[i]);
464 }
465 printf("\n");*/
466
467 return( len );
468}
469
Paul Bakker9397dcb2013-09-06 09:55:26 +0200470/*
471 * RelativeDistinguishedName ::=
472 * SET OF AttributeTypeAndValue
473 *
474 * AttributeTypeAndValue ::= SEQUENCE {
475 * type AttributeType,
476 * value AttributeValue }
477 *
478 * AttributeType ::= OBJECT IDENTIFIER
479 *
480 * AttributeValue ::= ANY DEFINED BY AttributeType
481 */
Paul Bakker5f45e622013-09-09 12:02:36 +0200482static int x509_write_name( unsigned char **p, unsigned char *start,
483 const char *oid, size_t oid_len,
484 const unsigned char *name, size_t name_len )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000485{
486 int ret;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000487 size_t len = 0;
488
Paul Bakker05888152012-02-16 10:26:57 +0000489 // Write PrintableString for all except OID_PKCS9_EMAIL
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000490 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200491 if( OID_SIZE( OID_PKCS9_EMAIL ) == oid_len &&
492 memcmp( oid, OID_PKCS9_EMAIL, oid_len ) == 0 )
Paul Bakker05888152012-02-16 10:26:57 +0000493 {
Paul Bakker5f45e622013-09-09 12:02:36 +0200494 ASN1_CHK_ADD( len, asn1_write_ia5_string( p, start,
495 (const char *) name,
496 name_len ) );
Paul Bakker05888152012-02-16 10:26:57 +0000497 }
498 else
Paul Bakker5f45e622013-09-09 12:02:36 +0200499 {
500 ASN1_CHK_ADD( len, asn1_write_printable_string( p, start,
501 (const char *) name,
502 name_len ) );
503 }
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000504
505 // Write OID
506 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200507 ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000508
Paul Bakker5f45e622013-09-09 12:02:36 +0200509 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000510 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
511
512 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
513 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) );
514
515 return( len );
516}
517
Paul Bakker9397dcb2013-09-06 09:55:26 +0200518static int x509_write_names( unsigned char **p, unsigned char *start,
Paul Bakker5f45e622013-09-09 12:02:36 +0200519 asn1_named_data *first )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200520{
521 int ret;
522 size_t len = 0;
Paul Bakker5f45e622013-09-09 12:02:36 +0200523 asn1_named_data *cur = first;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200524
525 while( cur != NULL )
526 {
Paul Bakker5f45e622013-09-09 12:02:36 +0200527 ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p,
528 cur->oid.len,
529 cur->val.p, cur->val.len ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200530 cur = cur->next;
531 }
532
533 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
534 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
535
536 return( len );
537}
538
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200539static int x509_write_sig( unsigned char **p, unsigned char *start,
540 const char *oid, unsigned char *sig, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000541{
542 int ret;
543 size_t len = 0;
544
545 if( *p - start < (int) size + 1 )
546 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
547
548 len = size;
549 (*p) -= len;
550 memcpy( *p, sig, len );
551
552 *--(*p) = 0;
553 len += 1;
554
555 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
556 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
557
558 // Write OID
559 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200560 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid,
561 strlen( oid ) ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000562
563 return( len );
564}
565
Paul Bakker9397dcb2013-09-06 09:55:26 +0200566static int x509_write_time( unsigned char **p, unsigned char *start,
567 const char *time, size_t size )
568{
569 int ret;
570 size_t len = 0;
571
Paul Bakker9c208aa2013-09-08 15:44:31 +0200572 /*
573 * write ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
574 */
575 if( time[0] == '2' && time[1] == '0' && time [2] < '5' )
576 {
577 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
578 (const unsigned char *) time + 2,
579 size - 2 ) );
580 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
581 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_UTC_TIME ) );
582 }
583 else
584 {
585 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
586 (const unsigned char *) time,
587 size ) );
588 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
589 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_GENERALIZED_TIME ) );
590 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200591
592 return( len );
593}
594
Paul Bakker15162a02013-09-06 19:27:21 +0200595static int x509_write_extension( unsigned char **p, unsigned char *start,
596 asn1_named_data *ext )
597{
598 int ret;
599 size_t len = 0;
600
601 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->val.p + 1,
602 ext->val.len - 1 ) );
603 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->val.len - 1 ) );
604 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) );
605
606 if( ext->val.p[0] != 0 )
607 {
608 ASN1_CHK_ADD( len, asn1_write_bool( p, start, 1 ) );
609 }
610
611 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->oid.p,
612 ext->oid.len ) );
613 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->oid.len ) );
614 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) );
615
616 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
617 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
618
619 return( len );
620}
621
622/*
623 * Extension ::= SEQUENCE {
624 * extnID OBJECT IDENTIFIER,
625 * critical BOOLEAN DEFAULT FALSE,
626 * extnValue OCTET STRING
627 * -- contains the DER encoding of an ASN.1 value
628 * -- corresponding to the extension type identified
629 * -- by extnID
630 * }
631 */
632static int x509_write_extensions( unsigned char **p, unsigned char *start,
633 asn1_named_data *first )
634{
635 int ret;
636 size_t len = 0;
637 asn1_named_data *cur_ext = first;
638
639 while( cur_ext != NULL )
640 {
641 ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
642 cur_ext = cur_ext->next;
643 }
644
645 return( len );
646}
647
Paul Bakkercd358032013-09-09 12:08:11 +0200648int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000649{
650 int ret;
Paul Bakkerc70b9822013-04-07 22:00:46 +0200651 const char *sig_oid;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000652 unsigned char *c, *c2;
Paul Bakker3cac5e02012-02-16 14:08:06 +0000653 unsigned char hash[64];
654 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000655 unsigned char tmp_buf[2048];
Paul Bakker9397dcb2013-09-06 09:55:26 +0200656 size_t pub_len = 0, sig_len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000657 size_t len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000658
659 c = tmp_buf + 2048 - 1;
660
Paul Bakker15162a02013-09-06 19:27:21 +0200661 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200662
Paul Bakkere5eae762013-08-26 12:05:14 +0200663 if( len )
Paul Bakkerfde42702013-08-25 14:47:27 +0200664 {
Paul Bakkere5eae762013-08-26 12:05:14 +0200665 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
666 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200667
Paul Bakkere5eae762013-08-26 12:05:14 +0200668 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
669 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200670
Paul Bakker5f45e622013-09-09 12:02:36 +0200671 ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ,
672 OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200673
Paul Bakkere5eae762013-08-26 12:05:14 +0200674 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
675 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200676 }
677
Paul Bakkere5eae762013-08-26 12:05:14 +0200678 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000679 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) );
680
Paul Bakker8eabfc12013-08-25 10:18:25 +0200681 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->rsa->E ) );
682 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->rsa->N ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000683
684 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
685 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
686
687 if( c - tmp_buf < 1 )
688 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
689
Paul Bakker8eabfc12013-08-25 10:18:25 +0200690 /*
691 * AlgorithmIdentifier ::= SEQUENCE {
692 * algorithm OBJECT IDENTIFIER,
693 * parameters ANY DEFINED BY algorithm OPTIONAL }
694 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000695 *--c = 0;
696 pub_len += 1;
697
698 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
699 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_BIT_STRING ) );
700
Paul Bakker5f45e622013-09-09 12:02:36 +0200701 ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf,
702 OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000703
704 len += pub_len;
705 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) );
706 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
707
Paul Bakker9397dcb2013-09-06 09:55:26 +0200708 /*
709 * Subject ::= Name
710 */
711 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000712
Paul Bakker8eabfc12013-08-25 10:18:25 +0200713 /*
714 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
715 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000716 ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
717
718 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
719 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200720
Paul Bakker8eabfc12013-08-25 10:18:25 +0200721 md( md_info_from_type( ctx->md_alg ), c, len, hash );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000722
Paul Bakker8eabfc12013-08-25 10:18:25 +0200723 rsa_pkcs1_sign( ctx->rsa, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000724
725 // Generate correct OID
726 //
Paul Bakker8eabfc12013-08-25 10:18:25 +0200727 ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000728
729 c2 = buf + size - 1;
Paul Bakker8eabfc12013-08-25 10:18:25 +0200730 ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig, ctx->rsa->len ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200731
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000732 c2 -= len;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200733 memcpy( c2, c, len );
734
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000735 len += sig_len;
736 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
737 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
738
739 return( len );
740}
741
Paul Bakker9397dcb2013-09-06 09:55:26 +0200742int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size )
743{
744 int ret;
745 const char *sig_oid;
746 unsigned char *c, *c2;
747 unsigned char hash[64];
748 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
749 unsigned char tmp_buf[2048];
750 size_t sub_len = 0, pub_len = 0, sig_len = 0;
751 size_t len = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200752
753 c = tmp_buf + 2048 - 1;
754
755 // Generate correct OID
756 //
757 ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid );
758 if( ret != 0 )
759 return( ret );
760
Paul Bakker15162a02013-09-06 19:27:21 +0200761 /*
762 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
763 */
764 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
765 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
766 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
767 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
768 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200769
770 /*
771 * SubjectPublicKeyInfo ::= SEQUENCE {
772 * algorithm AlgorithmIdentifier,
773 * subjectPublicKey BIT STRING }
774 */
775 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->subject_key->E ) );
776 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->subject_key->N ) );
777
778 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
779 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
780
781 if( c - tmp_buf < 1 )
782 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
783
784 *--c = 0;
785 pub_len += 1;
786
787 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
788 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_BIT_STRING ) );
789
Paul Bakker5f45e622013-09-09 12:02:36 +0200790 ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf,
791 OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200792
793 len += pub_len;
794 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) );
795 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
796
797 /*
798 * Subject ::= Name
799 */
800 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
801
802 /*
803 * Validity ::= SEQUENCE {
804 * notBefore Time,
805 * notAfter Time }
806 */
807 sub_len = 0;
808
809 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
810 X509_RFC5280_UTC_TIME_LEN ) );
811
812 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
813 X509_RFC5280_UTC_TIME_LEN ) );
814
815 len += sub_len;
816 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
817 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
818
819 /*
820 * Issuer ::= Name
821 */
822 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->issuer ) );
823
824 /*
825 * Signature ::= AlgorithmIdentifier
826 */
827 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf,
Paul Bakker5f45e622013-09-09 12:02:36 +0200828 sig_oid, strlen( sig_oid ) ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200829
830 /*
831 * Serial ::= INTEGER
832 */
833 ASN1_CHK_ADD( len, asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
834
835 /*
836 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
837 */
838 sub_len = 0;
839 ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) );
840 len += sub_len;
841 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
842 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) );
843
844 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
845 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
846
847 md( md_info_from_type( ctx->md_alg ), c, len, hash );
848
849 rsa_pkcs1_sign( ctx->issuer_key, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig );
850
851 c2 = buf + size - 1;
852 ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig, ctx->issuer_key->len ) );
853
854 c2 -= len;
855 memcpy( c2, c, len );
856
857 len += sig_len;
858 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
859 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
860
861 return( len );
862}
863
864#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
865#define PEM_END_CRT "-----END CERTIFICATE-----\n"
866
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200867#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n"
868#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n"
869
870#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n"
871#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n"
872
873#define PEM_BEGIN_PRIVATE_KEY "-----BEGIN RSA PRIVATE KEY-----\n"
874#define PEM_END_PRIVATE_KEY "-----END RSA PRIVATE KEY-----\n"
Paul Bakker135f1e92013-08-26 16:54:13 +0200875
876#if defined(POLARSSL_BASE64_C)
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200877static int x509write_pemify( const char *begin_str, const char *end_str,
878 const unsigned char *der_data, size_t der_len,
879 unsigned char *buf, size_t size )
Paul Bakker135f1e92013-08-26 16:54:13 +0200880{
881 int ret;
Paul Bakker135f1e92013-08-26 16:54:13 +0200882 unsigned char base_buf[4096];
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200883 unsigned char *c = base_buf, *p = buf;
884 size_t len = 0, olen = sizeof(base_buf);
Paul Bakker135f1e92013-08-26 16:54:13 +0200885
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200886 if( ( ret = base64_encode( base_buf, &olen, der_data, der_len ) ) != 0 )
Paul Bakker135f1e92013-08-26 16:54:13 +0200887 return( ret );
888
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200889 if( olen + strlen( begin_str ) + strlen( end_str ) +
Paul Bakker135f1e92013-08-26 16:54:13 +0200890 olen / 64 > size )
891 {
892 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
893 }
894
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200895 memcpy( p, begin_str, strlen( begin_str ) );
896 p += strlen( begin_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200897
898 while( olen )
899 {
900 len = ( olen > 64 ) ? 64 : olen;
901 memcpy( p, c, len );
902 olen -= len;
903 p += len;
904 c += len;
905 *p++ = '\n';
906 }
907
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200908 memcpy( p, end_str, strlen( end_str ) );
909 p += strlen( end_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200910
911 *p = '\0';
912
913 return( 0 );
914}
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200915
Paul Bakker9397dcb2013-09-06 09:55:26 +0200916int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size )
917{
918 int ret;
919 unsigned char output_buf[4096];
920
921 if( ( ret = x509write_crt_der( crt, output_buf,
922 sizeof(output_buf) ) ) < 0 )
923 {
924 return( ret );
925 }
926
927 if( ( ret = x509write_pemify( PEM_BEGIN_CRT, PEM_END_CRT,
928 output_buf + sizeof(output_buf) - 1 - ret,
929 ret, buf, size ) ) != 0 )
930 {
931 return( ret );
932 }
933
934 return( 0 );
935}
936
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200937int x509write_pubkey_pem( rsa_context *rsa, unsigned char *buf, size_t size )
938{
939 int ret;
940 unsigned char output_buf[4096];
941
942 if( ( ret = x509write_pubkey_der( rsa, output_buf,
943 sizeof(output_buf) ) ) < 0 )
944 {
945 return( ret );
946 }
947
948 if( ( ret = x509write_pemify( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
949 output_buf + sizeof(output_buf) - 1 - ret,
950 ret, buf, size ) ) != 0 )
951 {
952 return( ret );
953 }
954
955 return( 0 );
956}
957
958int x509write_key_pem( rsa_context *rsa, unsigned char *buf, size_t size )
959{
960 int ret;
961 unsigned char output_buf[4096];
962
963 if( ( ret = x509write_key_der( rsa, output_buf,
964 sizeof(output_buf) ) ) < 0 )
965 {
966 return( ret );
967 }
968
969 if( ( ret = x509write_pemify( PEM_BEGIN_PRIVATE_KEY, PEM_END_PRIVATE_KEY,
970 output_buf + sizeof(output_buf) - 1 - ret,
971 ret, buf, size ) ) != 0 )
972 {
973 return( ret );
974 }
975
976 return( 0 );
977}
978
Paul Bakkercd358032013-09-09 12:08:11 +0200979int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size )
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200980{
981 int ret;
982 unsigned char output_buf[4096];
983
984 if( ( ret = x509write_csr_der( ctx, output_buf,
985 sizeof(output_buf) ) ) < 0 )
986 {
987 return( ret );
988 }
989
990 if( ( ret = x509write_pemify( PEM_BEGIN_CSR, PEM_END_CSR,
991 output_buf + sizeof(output_buf) - 1 - ret,
992 ret, buf, size ) ) != 0 )
993 {
994 return( ret );
995 }
996
997 return( 0 );
998}
Paul Bakker135f1e92013-08-26 16:54:13 +0200999#endif /* POLARSSL_BASE64_C */
1000
Paul Bakkerbdb912d2012-02-13 23:11:30 +00001001#endif