blob: 35dc5bfe716c54238d442ed085dd69671dc306f0 [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
Manuel Pégourié-Gonnardda7317e2013-09-10 15:52:52 +020059 /* Clear existing chain if present */
60 asn1_free_named_data_list( head );
Paul Bakker8eabfc12013-08-25 10:18:25 +020061
62 while( c <= end )
63 {
64 if( in_tag && *c == '=' )
65 {
66 if( memcmp( s, "CN", 2 ) == 0 && c - s == 2 )
67 oid = OID_AT_CN;
68 else if( memcmp( s, "C", 1 ) == 0 && c - s == 1 )
69 oid = OID_AT_COUNTRY;
70 else if( memcmp( s, "O", 1 ) == 0 && c - s == 1 )
71 oid = OID_AT_ORGANIZATION;
72 else if( memcmp( s, "L", 1 ) == 0 && c - s == 1 )
73 oid = OID_AT_LOCALITY;
74 else if( memcmp( s, "R", 1 ) == 0 && c - s == 1 )
75 oid = OID_PKCS9_EMAIL;
76 else if( memcmp( s, "OU", 2 ) == 0 && c - s == 2 )
77 oid = OID_AT_ORG_UNIT;
78 else if( memcmp( s, "ST", 2 ) == 0 && c - s == 2 )
79 oid = OID_AT_STATE;
80 else
81 {
Paul Bakker0e06c0f2013-08-25 11:21:30 +020082 ret = POLARSSL_ERR_X509WRITE_UNKNOWN_OID;
Paul Bakker8eabfc12013-08-25 10:18:25 +020083 goto exit;
84 }
85
86 s = c + 1;
87 in_tag = 0;
88 }
89
90 if( !in_tag && ( *c == ',' || c == end ) )
91 {
Paul Bakker5f45e622013-09-09 12:02:36 +020092 if( ( cur = asn1_store_named_data( head, oid, strlen( oid ),
93 (unsigned char *) s,
94 c - s ) ) == NULL )
Paul Bakker8eabfc12013-08-25 10:18:25 +020095 {
Paul Bakker5f45e622013-09-09 12:02:36 +020096 return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
Paul Bakker8eabfc12013-08-25 10:18:25 +020097 }
98
Paul Bakkerd4bf8702013-09-09 13:59:11 +020099 while( c < end && *(c + 1) == ' ' )
100 c++;
101
Paul Bakker8eabfc12013-08-25 10:18:25 +0200102 s = c + 1;
103 in_tag = 1;
104 }
105 c++;
106 }
107
108exit:
109
110 return( ret );
111}
112
Paul Bakker15162a02013-09-06 19:27:21 +0200113/*
114 * RSAPublicKey ::= SEQUENCE {
115 * modulus INTEGER, -- n
116 * publicExponent INTEGER -- e
117 * }
118 */
119static int x509_write_rsa_pubkey( unsigned char **p, unsigned char *start,
120 rsa_context *rsa )
121{
122 int ret;
123 size_t len = 0;
124
125 ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->E ) );
126 ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->N ) );
127
128 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
129 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
130
131 return( len );
132}
133
Paul Bakkercd358032013-09-09 12:08:11 +0200134void x509write_csr_init( x509write_csr *ctx )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200135{
Paul Bakkercd358032013-09-09 12:08:11 +0200136 memset( ctx, 0, sizeof(x509write_csr) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200137}
138
Paul Bakkercd358032013-09-09 12:08:11 +0200139void x509write_csr_free( x509write_csr *ctx )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200140{
Paul Bakker5f45e622013-09-09 12:02:36 +0200141 asn1_free_named_data_list( &ctx->subject );
142 asn1_free_named_data_list( &ctx->extensions );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200143
Paul Bakkercd358032013-09-09 12:08:11 +0200144 memset( ctx, 0, sizeof(x509write_csr) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200145}
146
Paul Bakkercd358032013-09-09 12:08:11 +0200147void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200148{
149 ctx->md_alg = md_alg;
150}
151
Manuel Pégourié-Gonnard5353a032013-09-11 12:14:26 +0200152// TODO: take a pk_context
153// TODO: return int
Paul Bakkercd358032013-09-09 12:08:11 +0200154void x509write_csr_set_rsa_key( x509write_csr *ctx, rsa_context *rsa )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200155{
Manuel Pégourié-Gonnard5353a032013-09-11 12:14:26 +0200156 // temporary
157 ctx->key = polarssl_malloc( sizeof( pk_context ) );
158
159 // TODO: check errors
160 pk_init_ctx( ctx->key, pk_info_from_type( POLARSSL_PK_RSA ) );
161 rsa_copy( pk_rsa( *ctx->key ), rsa );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200162}
163
Paul Bakkercd358032013-09-09 12:08:11 +0200164int x509write_csr_set_subject_name( x509write_csr *ctx, char *subject_name )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200165{
166 return x509write_string_to_names( &ctx->subject, subject_name );
167}
168
Paul Bakker15162a02013-09-06 19:27:21 +0200169/* The first byte of the value in the asn1_named_data structure is reserved
170 * to store the critical boolean for us
171 */
172static int x509_set_extension( asn1_named_data **head,
173 const char *oid, size_t oid_len,
174 int critical,
175 const unsigned char *val, size_t val_len )
Paul Bakkerfde42702013-08-25 14:47:27 +0200176{
Paul Bakkere5eae762013-08-26 12:05:14 +0200177 asn1_named_data *cur;
Paul Bakkere5eae762013-08-26 12:05:14 +0200178
Paul Bakker59ba59f2013-09-09 11:26:00 +0200179 if( ( cur = asn1_store_named_data( head, oid, oid_len,
180 NULL, val_len + 1 ) ) == NULL )
Paul Bakkere5eae762013-08-26 12:05:14 +0200181 {
Paul Bakker59ba59f2013-09-09 11:26:00 +0200182 return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
Paul Bakker1c0e5502013-08-26 13:41:01 +0200183 }
184
Paul Bakker15162a02013-09-06 19:27:21 +0200185 cur->val.p[0] = critical;
186 memcpy( cur->val.p + 1, val, val_len );
Paul Bakker1c0e5502013-08-26 13:41:01 +0200187
188 return( 0 );
189}
190
Paul Bakkercd358032013-09-09 12:08:11 +0200191int x509write_csr_set_extension( x509write_csr *ctx,
Paul Bakker15162a02013-09-06 19:27:21 +0200192 const char *oid, size_t oid_len,
193 const unsigned char *val, size_t val_len )
194{
195 return x509_set_extension( &ctx->extensions, oid, oid_len,
196 0, val, val_len );
197}
198
Paul Bakkercd358032013-09-09 12:08:11 +0200199int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200200{
201 unsigned char buf[4];
202 unsigned char *c;
203 int ret;
204
205 c = buf + 4;
206
Paul Bakker624d03a2013-08-26 14:12:57 +0200207 if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200208 return( ret );
209
210 ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE,
211 OID_SIZE( OID_KEY_USAGE ),
212 buf, 4 );
213 if( ret != 0 )
214 return( ret );
215
216 return( 0 );
217}
218
Paul Bakkercd358032013-09-09 12:08:11 +0200219int x509write_csr_set_ns_cert_type( x509write_csr *ctx,
220 unsigned char ns_cert_type )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200221{
222 unsigned char buf[4];
223 unsigned char *c;
224 int ret;
225
226 c = buf + 4;
227
228 if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
229 return( ret );
230
231 ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE,
232 OID_SIZE( OID_NS_CERT_TYPE ),
233 buf, 4 );
234 if( ret != 0 )
235 return( ret );
Paul Bakkere5eae762013-08-26 12:05:14 +0200236
237 return( 0 );
Paul Bakkerfde42702013-08-25 14:47:27 +0200238}
239
Paul Bakker9397dcb2013-09-06 09:55:26 +0200240void x509write_crt_init( x509write_cert *ctx )
241{
242 memset( ctx, 0, sizeof(x509write_cert) );
243
244 mpi_init( &ctx->serial );
245 ctx->version = X509_CRT_VERSION_3;
246}
247
248void x509write_crt_free( x509write_cert *ctx )
249{
Paul Bakker9397dcb2013-09-06 09:55:26 +0200250 mpi_free( &ctx->serial );
251
Paul Bakker5f45e622013-09-09 12:02:36 +0200252 asn1_free_named_data_list( &ctx->subject );
253 asn1_free_named_data_list( &ctx->issuer );
254 asn1_free_named_data_list( &ctx->extensions );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200255
Paul Bakkercd358032013-09-09 12:08:11 +0200256 memset( ctx, 0, sizeof(x509write_csr) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200257}
258
259void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg )
260{
261 ctx->md_alg = md_alg;
262}
263
264void x509write_crt_set_subject_key( x509write_cert *ctx, rsa_context *rsa )
265{
266 ctx->subject_key = rsa;
267}
268
269void x509write_crt_set_issuer_key( x509write_cert *ctx, rsa_context *rsa )
270{
271 ctx->issuer_key = rsa;
272}
273
274int x509write_crt_set_subject_name( x509write_cert *ctx, char *subject_name )
275{
276 return x509write_string_to_names( &ctx->subject, subject_name );
277}
278
279int x509write_crt_set_issuer_name( x509write_cert *ctx, char *issuer_name )
280{
281 return x509write_string_to_names( &ctx->issuer, issuer_name );
282}
283
284int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial )
285{
286 int ret;
287
288 if( ( ret = mpi_copy( &ctx->serial, serial ) ) != 0 )
289 return( ret );
290
291 return( 0 );
292}
293
294int x509write_crt_set_validity( x509write_cert *ctx, char *not_before,
295 char *not_after )
296{
297 if( strlen(not_before) != X509_RFC5280_UTC_TIME_LEN - 1 ||
298 strlen(not_after) != X509_RFC5280_UTC_TIME_LEN - 1 )
299 {
300 return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
301 }
302 strncpy( ctx->not_before, not_before, X509_RFC5280_UTC_TIME_LEN );
303 strncpy( ctx->not_after , not_after , X509_RFC5280_UTC_TIME_LEN );
304 ctx->not_before[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
305 ctx->not_after[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
306
307 return( 0 );
308}
309
Paul Bakker15162a02013-09-06 19:27:21 +0200310int x509write_crt_set_extension( x509write_cert *ctx,
311 const char *oid, size_t oid_len,
312 int critical,
313 const unsigned char *val, size_t val_len )
314{
315 return x509_set_extension( &ctx->extensions, oid, oid_len,
316 critical, val, val_len );
317}
318
319int x509write_crt_set_basic_constraints( x509write_cert *ctx,
320 int is_ca, int max_pathlen )
321{
322 int ret;
323 unsigned char buf[9];
324 unsigned char *c = buf + sizeof(buf);
325 size_t len = 0;
326
327 memset( buf, 0, sizeof(buf) );
328
329 if( is_ca && max_pathlen > 127 )
330 return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
331
332 if( is_ca )
333 {
334 if( max_pathlen >= 0 )
335 {
336 ASN1_CHK_ADD( len, asn1_write_int( &c, buf, max_pathlen ) );
337 }
338 ASN1_CHK_ADD( len, asn1_write_bool( &c, buf, 1 ) );
339 }
340
341 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
342 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
343
344 return x509write_crt_set_extension( ctx, OID_BASIC_CONSTRAINTS,
345 OID_SIZE( OID_BASIC_CONSTRAINTS ),
346 0, buf + sizeof(buf) - len, len );
347}
348
349int x509write_crt_set_subject_key_identifier( x509write_cert *ctx )
350{
351 int ret;
352 unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
353 unsigned char *c = buf + sizeof(buf);
354 size_t len = 0;
355
356 memset( buf, 0, sizeof(buf));
357 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, ctx->subject_key ) );
358
359 sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
360 c = buf + sizeof(buf) - 20;
361 len = 20;
362
363 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
364 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_OCTET_STRING ) );
365
366 return x509write_crt_set_extension( ctx, OID_SUBJECT_KEY_IDENTIFIER,
367 OID_SIZE( OID_SUBJECT_KEY_IDENTIFIER ),
368 0, buf + sizeof(buf) - len, len );
369}
370
371int x509write_crt_set_authority_key_identifier( x509write_cert *ctx )
372{
373 int ret;
374 unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
375 unsigned char *c = buf + sizeof(buf);
376 size_t len = 0;
377
378 memset( buf, 0, sizeof(buf));
379 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, ctx->issuer_key ) );
380
381 sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
382 c = buf + sizeof(buf) - 20;
383 len = 20;
384
385 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
386 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONTEXT_SPECIFIC | 0 ) );
387
388 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
389 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
390
391 return x509write_crt_set_extension( ctx, OID_AUTHORITY_KEY_IDENTIFIER,
392 OID_SIZE( OID_AUTHORITY_KEY_IDENTIFIER ),
393 0, buf + sizeof(buf) - len, len );
394}
395
Paul Bakker52be08c2013-09-09 12:37:54 +0200396int x509write_crt_set_key_usage( x509write_cert *ctx, unsigned char key_usage )
397{
398 unsigned char buf[4];
399 unsigned char *c;
400 int ret;
401
402 c = buf + 4;
403
404 if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
405 return( ret );
406
407 ret = x509write_crt_set_extension( ctx, OID_KEY_USAGE,
408 OID_SIZE( OID_KEY_USAGE ),
409 1, buf, 4 );
410 if( ret != 0 )
411 return( ret );
412
413 return( 0 );
414}
415
416int x509write_crt_set_ns_cert_type( x509write_cert *ctx,
417 unsigned char ns_cert_type )
418{
419 unsigned char buf[4];
420 unsigned char *c;
421 int ret;
422
423 c = buf + 4;
424
425 if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
426 return( ret );
427
428 ret = x509write_crt_set_extension( ctx, OID_NS_CERT_TYPE,
429 OID_SIZE( OID_NS_CERT_TYPE ),
430 0, buf, 4 );
431 if( ret != 0 )
432 return( ret );
433
434 return( 0 );
435}
436
Paul Bakker82e29452013-08-25 11:01:31 +0200437int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000438{
439 int ret;
440 unsigned char *c;
441 size_t len = 0;
442
443 c = buf + size - 1;
444
Paul Bakker15162a02013-09-06 19:27:21 +0200445 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, rsa ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000446
447 if( c - buf < 1 )
448 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
449
Paul Bakker8eabfc12013-08-25 10:18:25 +0200450 /*
451 * SubjectPublicKeyInfo ::= SEQUENCE {
452 * algorithm AlgorithmIdentifier,
453 * subjectPublicKey BIT STRING }
454 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000455 *--c = 0;
456 len += 1;
457
458 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
459 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) );
460
Paul Bakker5f45e622013-09-09 12:02:36 +0200461 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf,
462 OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000463
464 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
465 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
466
467 return( len );
468}
469
Paul Bakker82e29452013-08-25 11:01:31 +0200470int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000471{
472 int ret;
473 unsigned char *c;
474 size_t len = 0;
475
476 c = buf + size - 1;
477
478 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) );
479 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) );
480 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) );
481 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) );
482 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) );
483 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) );
484 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) );
485 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) );
486 ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) );
487
488 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
489 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
490
491 // TODO: Make NON RSA Specific variant later on
492/* *--c = 0;
493 len += 1;
494
495 len += asn1_write_len( &c, len);
496 len += asn1_write_tag( &c, ASN1_BIT_STRING );
497
498 len += asn1_write_oid( &c, OID_PKCS1_RSA );
499
500 len += asn1_write_int( &c, 0 );
501
502 len += asn1_write_len( &c, len);
503 len += asn1_write_tag( &c, ASN1_CONSTRUCTED | ASN1_SEQUENCE );*/
504
505/* for(i = 0; i < len; ++i)
506 {
507 if (i % 16 == 0 ) printf("\n");
508 printf("%02x ", c[i]);
509 }
510 printf("\n");*/
511
512 return( len );
513}
514
Paul Bakker9397dcb2013-09-06 09:55:26 +0200515/*
516 * RelativeDistinguishedName ::=
517 * SET OF AttributeTypeAndValue
518 *
519 * AttributeTypeAndValue ::= SEQUENCE {
520 * type AttributeType,
521 * value AttributeValue }
522 *
523 * AttributeType ::= OBJECT IDENTIFIER
524 *
525 * AttributeValue ::= ANY DEFINED BY AttributeType
526 */
Paul Bakker5f45e622013-09-09 12:02:36 +0200527static int x509_write_name( unsigned char **p, unsigned char *start,
528 const char *oid, size_t oid_len,
529 const unsigned char *name, size_t name_len )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000530{
531 int ret;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000532 size_t len = 0;
533
Paul Bakker05888152012-02-16 10:26:57 +0000534 // Write PrintableString for all except OID_PKCS9_EMAIL
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000535 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200536 if( OID_SIZE( OID_PKCS9_EMAIL ) == oid_len &&
537 memcmp( oid, OID_PKCS9_EMAIL, oid_len ) == 0 )
Paul Bakker05888152012-02-16 10:26:57 +0000538 {
Paul Bakker5f45e622013-09-09 12:02:36 +0200539 ASN1_CHK_ADD( len, asn1_write_ia5_string( p, start,
540 (const char *) name,
541 name_len ) );
Paul Bakker05888152012-02-16 10:26:57 +0000542 }
543 else
Paul Bakker5f45e622013-09-09 12:02:36 +0200544 {
545 ASN1_CHK_ADD( len, asn1_write_printable_string( p, start,
546 (const char *) name,
547 name_len ) );
548 }
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000549
550 // Write OID
551 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200552 ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000553
Paul Bakker5f45e622013-09-09 12:02:36 +0200554 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000555 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
556
557 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
558 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) );
559
560 return( len );
561}
562
Paul Bakker9397dcb2013-09-06 09:55:26 +0200563static int x509_write_names( unsigned char **p, unsigned char *start,
Paul Bakker5f45e622013-09-09 12:02:36 +0200564 asn1_named_data *first )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200565{
566 int ret;
567 size_t len = 0;
Paul Bakker5f45e622013-09-09 12:02:36 +0200568 asn1_named_data *cur = first;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200569
570 while( cur != NULL )
571 {
Paul Bakker5f45e622013-09-09 12:02:36 +0200572 ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p,
573 cur->oid.len,
574 cur->val.p, cur->val.len ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200575 cur = cur->next;
576 }
577
578 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
579 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
580
581 return( len );
582}
583
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200584static int x509_write_sig( unsigned char **p, unsigned char *start,
Paul Bakker1c3853b2013-09-10 11:43:44 +0200585 const char *oid, size_t oid_len,
586 unsigned char *sig, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000587{
588 int ret;
589 size_t len = 0;
590
591 if( *p - start < (int) size + 1 )
592 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
593
594 len = size;
595 (*p) -= len;
596 memcpy( *p, sig, len );
597
598 *--(*p) = 0;
599 len += 1;
600
601 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
602 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
603
604 // Write OID
605 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200606 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid,
Paul Bakker1c3853b2013-09-10 11:43:44 +0200607 oid_len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000608
609 return( len );
610}
611
Paul Bakker9397dcb2013-09-06 09:55:26 +0200612static int x509_write_time( unsigned char **p, unsigned char *start,
613 const char *time, size_t size )
614{
615 int ret;
616 size_t len = 0;
617
Paul Bakker9c208aa2013-09-08 15:44:31 +0200618 /*
619 * write ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
620 */
621 if( time[0] == '2' && time[1] == '0' && time [2] < '5' )
622 {
623 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
624 (const unsigned char *) time + 2,
625 size - 2 ) );
626 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
627 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_UTC_TIME ) );
628 }
629 else
630 {
631 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
632 (const unsigned char *) time,
633 size ) );
634 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
635 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_GENERALIZED_TIME ) );
636 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200637
638 return( len );
639}
640
Paul Bakker15162a02013-09-06 19:27:21 +0200641static int x509_write_extension( unsigned char **p, unsigned char *start,
642 asn1_named_data *ext )
643{
644 int ret;
645 size_t len = 0;
646
647 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->val.p + 1,
648 ext->val.len - 1 ) );
649 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->val.len - 1 ) );
650 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) );
651
652 if( ext->val.p[0] != 0 )
653 {
654 ASN1_CHK_ADD( len, asn1_write_bool( p, start, 1 ) );
655 }
656
657 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->oid.p,
658 ext->oid.len ) );
659 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->oid.len ) );
660 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) );
661
662 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
663 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
664
665 return( len );
666}
667
668/*
669 * Extension ::= SEQUENCE {
670 * extnID OBJECT IDENTIFIER,
671 * critical BOOLEAN DEFAULT FALSE,
672 * extnValue OCTET STRING
673 * -- contains the DER encoding of an ASN.1 value
674 * -- corresponding to the extension type identified
675 * -- by extnID
676 * }
677 */
678static int x509_write_extensions( unsigned char **p, unsigned char *start,
679 asn1_named_data *first )
680{
681 int ret;
682 size_t len = 0;
683 asn1_named_data *cur_ext = first;
684
685 while( cur_ext != NULL )
686 {
687 ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
688 cur_ext = cur_ext->next;
689 }
690
691 return( len );
692}
693
Paul Bakkercd358032013-09-09 12:08:11 +0200694int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000695{
696 int ret;
Paul Bakkerc70b9822013-04-07 22:00:46 +0200697 const char *sig_oid;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200698 size_t sig_oid_len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000699 unsigned char *c, *c2;
Paul Bakker3cac5e02012-02-16 14:08:06 +0000700 unsigned char hash[64];
701 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000702 unsigned char tmp_buf[2048];
Paul Bakker9397dcb2013-09-06 09:55:26 +0200703 size_t pub_len = 0, sig_len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000704 size_t len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000705
706 c = tmp_buf + 2048 - 1;
707
Paul Bakker15162a02013-09-06 19:27:21 +0200708 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200709
Paul Bakkere5eae762013-08-26 12:05:14 +0200710 if( len )
Paul Bakkerfde42702013-08-25 14:47:27 +0200711 {
Paul Bakkere5eae762013-08-26 12:05:14 +0200712 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
713 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
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_SET ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200717
Paul Bakker5f45e622013-09-09 12:02:36 +0200718 ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ,
719 OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200720
Paul Bakkere5eae762013-08-26 12:05:14 +0200721 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
722 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200723 }
724
Paul Bakkere5eae762013-08-26 12:05:14 +0200725 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000726 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) );
727
Manuel Pégourié-Gonnard6dcf0bf2013-09-11 13:09:04 +0200728 ASN1_CHK_ADD( pub_len, x509write_pubkey_der( pk_rsa( *ctx->key ),
729 tmp_buf, c - tmp_buf + 1 ) );
730 c -= pub_len;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000731 len += pub_len;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000732
Paul Bakker9397dcb2013-09-06 09:55:26 +0200733 /*
734 * Subject ::= Name
735 */
736 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000737
Paul Bakker8eabfc12013-08-25 10:18:25 +0200738 /*
739 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
740 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000741 ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
742
743 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
744 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200745
Paul Bakker8eabfc12013-08-25 10:18:25 +0200746 md( md_info_from_type( ctx->md_alg ), c, len, hash );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000747
Manuel Pégourié-Gonnard5353a032013-09-11 12:14:26 +0200748 if( !pk_can_do( ctx->key, POLARSSL_PK_RSA ) )
749 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
750
751 // TODO: use pk_sign()
752 rsa_pkcs1_sign( pk_rsa( *ctx->key ), NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000753
754 // Generate correct OID
755 //
Manuel Pégourié-Gonnard5353a032013-09-11 12:14:26 +0200756 // TODO: use pk_info->type
Paul Bakker1c3853b2013-09-10 11:43:44 +0200757 ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid,
758 &sig_oid_len );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000759
Manuel Pégourié-Gonnard5353a032013-09-11 12:14:26 +0200760 // TODO: use pk_get_len()
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000761 c2 = buf + size - 1;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200762 ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len,
Manuel Pégourié-Gonnard5353a032013-09-11 12:14:26 +0200763 sig, pk_rsa( *ctx->key )->len ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200764
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000765 c2 -= len;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200766 memcpy( c2, c, len );
767
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000768 len += sig_len;
769 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
770 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
771
772 return( len );
773}
774
Paul Bakker9397dcb2013-09-06 09:55:26 +0200775int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size )
776{
777 int ret;
778 const char *sig_oid;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200779 size_t sig_oid_len = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200780 unsigned char *c, *c2;
781 unsigned char hash[64];
782 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
783 unsigned char tmp_buf[2048];
784 size_t sub_len = 0, pub_len = 0, sig_len = 0;
785 size_t len = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200786
787 c = tmp_buf + 2048 - 1;
788
789 // Generate correct OID
790 //
Paul Bakker1c3853b2013-09-10 11:43:44 +0200791 ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid,
792 &sig_oid_len );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200793 if( ret != 0 )
794 return( ret );
795
Paul Bakker15162a02013-09-06 19:27:21 +0200796 /*
797 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
798 */
799 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
800 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
801 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
802 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
803 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200804
805 /*
Manuel Pégourié-Gonnard6dcf0bf2013-09-11 13:09:04 +0200806 * SubjectPublicKeyInfo
Paul Bakker9397dcb2013-09-06 09:55:26 +0200807 */
Manuel Pégourié-Gonnard6dcf0bf2013-09-11 13:09:04 +0200808 ASN1_CHK_ADD( pub_len, x509write_pubkey_der( ctx->subject_key,
809 tmp_buf, c - tmp_buf + 1 ) );
810 c -= pub_len;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200811 len += pub_len;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200812
813 /*
814 * Subject ::= Name
815 */
816 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
817
818 /*
819 * Validity ::= SEQUENCE {
820 * notBefore Time,
821 * notAfter Time }
822 */
823 sub_len = 0;
824
825 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
826 X509_RFC5280_UTC_TIME_LEN ) );
827
828 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
829 X509_RFC5280_UTC_TIME_LEN ) );
830
831 len += sub_len;
832 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
833 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
834
835 /*
836 * Issuer ::= Name
837 */
838 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->issuer ) );
839
840 /*
841 * Signature ::= AlgorithmIdentifier
842 */
843 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf,
Paul Bakker5f45e622013-09-09 12:02:36 +0200844 sig_oid, strlen( sig_oid ) ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200845
846 /*
847 * Serial ::= INTEGER
848 */
849 ASN1_CHK_ADD( len, asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
850
851 /*
852 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
853 */
854 sub_len = 0;
855 ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) );
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_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) );
859
860 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
861 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
862
863 md( md_info_from_type( ctx->md_alg ), c, len, hash );
864
865 rsa_pkcs1_sign( ctx->issuer_key, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig );
866
867 c2 = buf + size - 1;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200868 ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len,
869 sig, ctx->issuer_key->len ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200870
871 c2 -= len;
872 memcpy( c2, c, len );
873
874 len += sig_len;
875 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
876 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
877
878 return( len );
879}
880
881#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
882#define PEM_END_CRT "-----END CERTIFICATE-----\n"
883
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200884#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n"
885#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n"
886
887#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n"
888#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n"
889
890#define PEM_BEGIN_PRIVATE_KEY "-----BEGIN RSA PRIVATE KEY-----\n"
891#define PEM_END_PRIVATE_KEY "-----END RSA PRIVATE KEY-----\n"
Paul Bakker135f1e92013-08-26 16:54:13 +0200892
893#if defined(POLARSSL_BASE64_C)
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200894static int x509write_pemify( const char *begin_str, const char *end_str,
895 const unsigned char *der_data, size_t der_len,
896 unsigned char *buf, size_t size )
Paul Bakker135f1e92013-08-26 16:54:13 +0200897{
898 int ret;
Paul Bakker135f1e92013-08-26 16:54:13 +0200899 unsigned char base_buf[4096];
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200900 unsigned char *c = base_buf, *p = buf;
901 size_t len = 0, olen = sizeof(base_buf);
Paul Bakker135f1e92013-08-26 16:54:13 +0200902
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200903 if( ( ret = base64_encode( base_buf, &olen, der_data, der_len ) ) != 0 )
Paul Bakker135f1e92013-08-26 16:54:13 +0200904 return( ret );
905
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200906 if( olen + strlen( begin_str ) + strlen( end_str ) +
Paul Bakker135f1e92013-08-26 16:54:13 +0200907 olen / 64 > size )
908 {
909 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
910 }
911
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200912 memcpy( p, begin_str, strlen( begin_str ) );
913 p += strlen( begin_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200914
915 while( olen )
916 {
917 len = ( olen > 64 ) ? 64 : olen;
918 memcpy( p, c, len );
919 olen -= len;
920 p += len;
921 c += len;
922 *p++ = '\n';
923 }
924
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200925 memcpy( p, end_str, strlen( end_str ) );
926 p += strlen( end_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200927
928 *p = '\0';
929
930 return( 0 );
931}
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200932
Paul Bakker9397dcb2013-09-06 09:55:26 +0200933int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size )
934{
935 int ret;
936 unsigned char output_buf[4096];
937
938 if( ( ret = x509write_crt_der( crt, output_buf,
939 sizeof(output_buf) ) ) < 0 )
940 {
941 return( ret );
942 }
943
944 if( ( ret = x509write_pemify( PEM_BEGIN_CRT, PEM_END_CRT,
945 output_buf + sizeof(output_buf) - 1 - ret,
946 ret, buf, size ) ) != 0 )
947 {
948 return( ret );
949 }
950
951 return( 0 );
952}
953
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200954int x509write_pubkey_pem( rsa_context *rsa, unsigned char *buf, size_t size )
955{
956 int ret;
957 unsigned char output_buf[4096];
958
959 if( ( ret = x509write_pubkey_der( rsa, output_buf,
960 sizeof(output_buf) ) ) < 0 )
961 {
962 return( ret );
963 }
964
965 if( ( ret = x509write_pemify( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
966 output_buf + sizeof(output_buf) - 1 - ret,
967 ret, buf, size ) ) != 0 )
968 {
969 return( ret );
970 }
971
972 return( 0 );
973}
974
975int x509write_key_pem( rsa_context *rsa, unsigned char *buf, size_t size )
976{
977 int ret;
978 unsigned char output_buf[4096];
979
980 if( ( ret = x509write_key_der( rsa, output_buf,
981 sizeof(output_buf) ) ) < 0 )
982 {
983 return( ret );
984 }
985
986 if( ( ret = x509write_pemify( PEM_BEGIN_PRIVATE_KEY, PEM_END_PRIVATE_KEY,
987 output_buf + sizeof(output_buf) - 1 - ret,
988 ret, buf, size ) ) != 0 )
989 {
990 return( ret );
991 }
992
993 return( 0 );
994}
995
Paul Bakkercd358032013-09-09 12:08:11 +0200996int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size )
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200997{
998 int ret;
999 unsigned char output_buf[4096];
1000
1001 if( ( ret = x509write_csr_der( ctx, output_buf,
1002 sizeof(output_buf) ) ) < 0 )
1003 {
1004 return( ret );
1005 }
1006
1007 if( ( ret = x509write_pemify( PEM_BEGIN_CSR, PEM_END_CSR,
1008 output_buf + sizeof(output_buf) - 1 - ret,
1009 ret, buf, size ) ) != 0 )
1010 {
1011 return( ret );
1012 }
1013
1014 return( 0 );
1015}
Paul Bakker135f1e92013-08-26 16:54:13 +02001016#endif /* POLARSSL_BASE64_C */
1017
Paul Bakkerbdb912d2012-02-13 23:11:30 +00001018#endif