blob: aed66240e647ad87f77e84fd64a5fa9e15486761 [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 Bakkerd4bf8702013-09-09 13:59:11 +0200105 while( c < end && *(c + 1) == ' ' )
106 c++;
107
Paul Bakker8eabfc12013-08-25 10:18:25 +0200108 s = c + 1;
109 in_tag = 1;
110 }
111 c++;
112 }
113
114exit:
115
116 return( ret );
117}
118
Paul Bakker15162a02013-09-06 19:27:21 +0200119/*
120 * RSAPublicKey ::= SEQUENCE {
121 * modulus INTEGER, -- n
122 * publicExponent INTEGER -- e
123 * }
124 */
125static int x509_write_rsa_pubkey( unsigned char **p, unsigned char *start,
126 rsa_context *rsa )
127{
128 int ret;
129 size_t len = 0;
130
131 ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->E ) );
132 ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->N ) );
133
134 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
135 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
136
137 return( len );
138}
139
Paul Bakkercd358032013-09-09 12:08:11 +0200140void x509write_csr_init( x509write_csr *ctx )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200141{
Paul Bakkercd358032013-09-09 12:08:11 +0200142 memset( ctx, 0, sizeof(x509write_csr) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200143}
144
Paul Bakkercd358032013-09-09 12:08:11 +0200145void x509write_csr_free( x509write_csr *ctx )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200146{
Paul Bakker5f45e622013-09-09 12:02:36 +0200147 asn1_free_named_data_list( &ctx->subject );
148 asn1_free_named_data_list( &ctx->extensions );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200149
Paul Bakkercd358032013-09-09 12:08:11 +0200150 memset( ctx, 0, sizeof(x509write_csr) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200151}
152
Paul Bakkercd358032013-09-09 12:08:11 +0200153void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200154{
155 ctx->md_alg = md_alg;
156}
157
Paul Bakkercd358032013-09-09 12:08:11 +0200158void x509write_csr_set_rsa_key( x509write_csr *ctx, rsa_context *rsa )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200159{
160 ctx->rsa = rsa;
161}
162
Paul Bakkercd358032013-09-09 12:08:11 +0200163int x509write_csr_set_subject_name( x509write_csr *ctx, char *subject_name )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200164{
165 return x509write_string_to_names( &ctx->subject, subject_name );
166}
167
Paul Bakker15162a02013-09-06 19:27:21 +0200168/* The first byte of the value in the asn1_named_data structure is reserved
169 * to store the critical boolean for us
170 */
171static int x509_set_extension( asn1_named_data **head,
172 const char *oid, size_t oid_len,
173 int critical,
174 const unsigned char *val, size_t val_len )
Paul Bakkerfde42702013-08-25 14:47:27 +0200175{
Paul Bakkere5eae762013-08-26 12:05:14 +0200176 asn1_named_data *cur;
Paul Bakkere5eae762013-08-26 12:05:14 +0200177
Paul Bakker59ba59f2013-09-09 11:26:00 +0200178 if( ( cur = asn1_store_named_data( head, oid, oid_len,
179 NULL, val_len + 1 ) ) == NULL )
Paul Bakkere5eae762013-08-26 12:05:14 +0200180 {
Paul Bakker59ba59f2013-09-09 11:26:00 +0200181 return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
Paul Bakker1c0e5502013-08-26 13:41:01 +0200182 }
183
Paul Bakker15162a02013-09-06 19:27:21 +0200184 cur->val.p[0] = critical;
185 memcpy( cur->val.p + 1, val, val_len );
Paul Bakker1c0e5502013-08-26 13:41:01 +0200186
187 return( 0 );
188}
189
Paul Bakkercd358032013-09-09 12:08:11 +0200190int x509write_csr_set_extension( x509write_csr *ctx,
Paul Bakker15162a02013-09-06 19:27:21 +0200191 const char *oid, size_t oid_len,
192 const unsigned char *val, size_t val_len )
193{
194 return x509_set_extension( &ctx->extensions, oid, oid_len,
195 0, val, val_len );
196}
197
Paul Bakkercd358032013-09-09 12:08:11 +0200198int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200199{
200 unsigned char buf[4];
201 unsigned char *c;
202 int ret;
203
204 c = buf + 4;
205
Paul Bakker624d03a2013-08-26 14:12:57 +0200206 if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200207 return( ret );
208
209 ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE,
210 OID_SIZE( OID_KEY_USAGE ),
211 buf, 4 );
212 if( ret != 0 )
213 return( ret );
214
215 return( 0 );
216}
217
Paul Bakkercd358032013-09-09 12:08:11 +0200218int x509write_csr_set_ns_cert_type( x509write_csr *ctx,
219 unsigned char ns_cert_type )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200220{
221 unsigned char buf[4];
222 unsigned char *c;
223 int ret;
224
225 c = buf + 4;
226
227 if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
228 return( ret );
229
230 ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE,
231 OID_SIZE( OID_NS_CERT_TYPE ),
232 buf, 4 );
233 if( ret != 0 )
234 return( ret );
Paul Bakkere5eae762013-08-26 12:05:14 +0200235
236 return( 0 );
Paul Bakkerfde42702013-08-25 14:47:27 +0200237}
238
Paul Bakker9397dcb2013-09-06 09:55:26 +0200239void x509write_crt_init( x509write_cert *ctx )
240{
241 memset( ctx, 0, sizeof(x509write_cert) );
242
243 mpi_init( &ctx->serial );
244 ctx->version = X509_CRT_VERSION_3;
245}
246
247void x509write_crt_free( x509write_cert *ctx )
248{
Paul Bakker9397dcb2013-09-06 09:55:26 +0200249 mpi_free( &ctx->serial );
250
Paul Bakker5f45e622013-09-09 12:02:36 +0200251 asn1_free_named_data_list( &ctx->subject );
252 asn1_free_named_data_list( &ctx->issuer );
253 asn1_free_named_data_list( &ctx->extensions );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200254
Paul Bakkercd358032013-09-09 12:08:11 +0200255 memset( ctx, 0, sizeof(x509write_csr) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200256}
257
258void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg )
259{
260 ctx->md_alg = md_alg;
261}
262
263void x509write_crt_set_subject_key( x509write_cert *ctx, rsa_context *rsa )
264{
265 ctx->subject_key = rsa;
266}
267
268void x509write_crt_set_issuer_key( x509write_cert *ctx, rsa_context *rsa )
269{
270 ctx->issuer_key = rsa;
271}
272
273int x509write_crt_set_subject_name( x509write_cert *ctx, char *subject_name )
274{
275 return x509write_string_to_names( &ctx->subject, subject_name );
276}
277
278int x509write_crt_set_issuer_name( x509write_cert *ctx, char *issuer_name )
279{
280 return x509write_string_to_names( &ctx->issuer, issuer_name );
281}
282
283int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial )
284{
285 int ret;
286
287 if( ( ret = mpi_copy( &ctx->serial, serial ) ) != 0 )
288 return( ret );
289
290 return( 0 );
291}
292
293int x509write_crt_set_validity( x509write_cert *ctx, char *not_before,
294 char *not_after )
295{
296 if( strlen(not_before) != X509_RFC5280_UTC_TIME_LEN - 1 ||
297 strlen(not_after) != X509_RFC5280_UTC_TIME_LEN - 1 )
298 {
299 return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
300 }
301 strncpy( ctx->not_before, not_before, X509_RFC5280_UTC_TIME_LEN );
302 strncpy( ctx->not_after , not_after , X509_RFC5280_UTC_TIME_LEN );
303 ctx->not_before[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
304 ctx->not_after[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
305
306 return( 0 );
307}
308
Paul Bakker15162a02013-09-06 19:27:21 +0200309int x509write_crt_set_extension( x509write_cert *ctx,
310 const char *oid, size_t oid_len,
311 int critical,
312 const unsigned char *val, size_t val_len )
313{
314 return x509_set_extension( &ctx->extensions, oid, oid_len,
315 critical, val, val_len );
316}
317
318int x509write_crt_set_basic_constraints( x509write_cert *ctx,
319 int is_ca, int max_pathlen )
320{
321 int ret;
322 unsigned char buf[9];
323 unsigned char *c = buf + sizeof(buf);
324 size_t len = 0;
325
326 memset( buf, 0, sizeof(buf) );
327
328 if( is_ca && max_pathlen > 127 )
329 return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
330
331 if( is_ca )
332 {
333 if( max_pathlen >= 0 )
334 {
335 ASN1_CHK_ADD( len, asn1_write_int( &c, buf, max_pathlen ) );
336 }
337 ASN1_CHK_ADD( len, asn1_write_bool( &c, buf, 1 ) );
338 }
339
340 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
341 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
342
343 return x509write_crt_set_extension( ctx, OID_BASIC_CONSTRAINTS,
344 OID_SIZE( OID_BASIC_CONSTRAINTS ),
345 0, buf + sizeof(buf) - len, len );
346}
347
348int x509write_crt_set_subject_key_identifier( x509write_cert *ctx )
349{
350 int ret;
351 unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
352 unsigned char *c = buf + sizeof(buf);
353 size_t len = 0;
354
355 memset( buf, 0, sizeof(buf));
356 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, ctx->subject_key ) );
357
358 sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
359 c = buf + sizeof(buf) - 20;
360 len = 20;
361
362 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
363 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_OCTET_STRING ) );
364
365 return x509write_crt_set_extension( ctx, OID_SUBJECT_KEY_IDENTIFIER,
366 OID_SIZE( OID_SUBJECT_KEY_IDENTIFIER ),
367 0, buf + sizeof(buf) - len, len );
368}
369
370int x509write_crt_set_authority_key_identifier( x509write_cert *ctx )
371{
372 int ret;
373 unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
374 unsigned char *c = buf + sizeof(buf);
375 size_t len = 0;
376
377 memset( buf, 0, sizeof(buf));
378 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, ctx->issuer_key ) );
379
380 sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
381 c = buf + sizeof(buf) - 20;
382 len = 20;
383
384 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
385 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONTEXT_SPECIFIC | 0 ) );
386
387 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
388 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
389
390 return x509write_crt_set_extension( ctx, OID_AUTHORITY_KEY_IDENTIFIER,
391 OID_SIZE( OID_AUTHORITY_KEY_IDENTIFIER ),
392 0, buf + sizeof(buf) - len, len );
393}
394
Paul Bakker52be08c2013-09-09 12:37:54 +0200395int x509write_crt_set_key_usage( x509write_cert *ctx, unsigned char key_usage )
396{
397 unsigned char buf[4];
398 unsigned char *c;
399 int ret;
400
401 c = buf + 4;
402
403 if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
404 return( ret );
405
406 ret = x509write_crt_set_extension( ctx, OID_KEY_USAGE,
407 OID_SIZE( OID_KEY_USAGE ),
408 1, buf, 4 );
409 if( ret != 0 )
410 return( ret );
411
412 return( 0 );
413}
414
415int x509write_crt_set_ns_cert_type( x509write_cert *ctx,
416 unsigned char ns_cert_type )
417{
418 unsigned char buf[4];
419 unsigned char *c;
420 int ret;
421
422 c = buf + 4;
423
424 if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
425 return( ret );
426
427 ret = x509write_crt_set_extension( ctx, OID_NS_CERT_TYPE,
428 OID_SIZE( OID_NS_CERT_TYPE ),
429 0, buf, 4 );
430 if( ret != 0 )
431 return( ret );
432
433 return( 0 );
434}
435
Paul Bakker82e29452013-08-25 11:01:31 +0200436int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000437{
438 int ret;
439 unsigned char *c;
440 size_t len = 0;
441
442 c = buf + size - 1;
443
Paul Bakker15162a02013-09-06 19:27:21 +0200444 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, rsa ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000445
446 if( c - buf < 1 )
447 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
448
Paul Bakker8eabfc12013-08-25 10:18:25 +0200449 /*
450 * SubjectPublicKeyInfo ::= SEQUENCE {
451 * algorithm AlgorithmIdentifier,
452 * subjectPublicKey BIT STRING }
453 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000454 *--c = 0;
455 len += 1;
456
457 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
458 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) );
459
Paul Bakker5f45e622013-09-09 12:02:36 +0200460 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf,
461 OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000462
463 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
464 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
465
466 return( len );
467}
468
Paul Bakker82e29452013-08-25 11:01:31 +0200469int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000470{
471 int ret;
472 unsigned char *c;
473 size_t len = 0;
474
475 c = buf + size - 1;
476
477 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) );
478 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) );
479 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) );
480 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) );
481 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) );
482 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) );
483 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) );
484 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) );
485 ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) );
486
487 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
488 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
489
490 // TODO: Make NON RSA Specific variant later on
491/* *--c = 0;
492 len += 1;
493
494 len += asn1_write_len( &c, len);
495 len += asn1_write_tag( &c, ASN1_BIT_STRING );
496
497 len += asn1_write_oid( &c, OID_PKCS1_RSA );
498
499 len += asn1_write_int( &c, 0 );
500
501 len += asn1_write_len( &c, len);
502 len += asn1_write_tag( &c, ASN1_CONSTRUCTED | ASN1_SEQUENCE );*/
503
504/* for(i = 0; i < len; ++i)
505 {
506 if (i % 16 == 0 ) printf("\n");
507 printf("%02x ", c[i]);
508 }
509 printf("\n");*/
510
511 return( len );
512}
513
Paul Bakker9397dcb2013-09-06 09:55:26 +0200514/*
515 * RelativeDistinguishedName ::=
516 * SET OF AttributeTypeAndValue
517 *
518 * AttributeTypeAndValue ::= SEQUENCE {
519 * type AttributeType,
520 * value AttributeValue }
521 *
522 * AttributeType ::= OBJECT IDENTIFIER
523 *
524 * AttributeValue ::= ANY DEFINED BY AttributeType
525 */
Paul Bakker5f45e622013-09-09 12:02:36 +0200526static int x509_write_name( unsigned char **p, unsigned char *start,
527 const char *oid, size_t oid_len,
528 const unsigned char *name, size_t name_len )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000529{
530 int ret;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000531 size_t len = 0;
532
Paul Bakker05888152012-02-16 10:26:57 +0000533 // Write PrintableString for all except OID_PKCS9_EMAIL
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000534 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200535 if( OID_SIZE( OID_PKCS9_EMAIL ) == oid_len &&
536 memcmp( oid, OID_PKCS9_EMAIL, oid_len ) == 0 )
Paul Bakker05888152012-02-16 10:26:57 +0000537 {
Paul Bakker5f45e622013-09-09 12:02:36 +0200538 ASN1_CHK_ADD( len, asn1_write_ia5_string( p, start,
539 (const char *) name,
540 name_len ) );
Paul Bakker05888152012-02-16 10:26:57 +0000541 }
542 else
Paul Bakker5f45e622013-09-09 12:02:36 +0200543 {
544 ASN1_CHK_ADD( len, asn1_write_printable_string( p, start,
545 (const char *) name,
546 name_len ) );
547 }
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000548
549 // Write OID
550 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200551 ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000552
Paul Bakker5f45e622013-09-09 12:02:36 +0200553 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000554 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
555
556 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
557 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) );
558
559 return( len );
560}
561
Paul Bakker9397dcb2013-09-06 09:55:26 +0200562static int x509_write_names( unsigned char **p, unsigned char *start,
Paul Bakker5f45e622013-09-09 12:02:36 +0200563 asn1_named_data *first )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200564{
565 int ret;
566 size_t len = 0;
Paul Bakker5f45e622013-09-09 12:02:36 +0200567 asn1_named_data *cur = first;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200568
569 while( cur != NULL )
570 {
Paul Bakker5f45e622013-09-09 12:02:36 +0200571 ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p,
572 cur->oid.len,
573 cur->val.p, cur->val.len ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200574 cur = cur->next;
575 }
576
577 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
578 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
579
580 return( len );
581}
582
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200583static int x509_write_sig( unsigned char **p, unsigned char *start,
584 const char *oid, unsigned char *sig, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000585{
586 int ret;
587 size_t len = 0;
588
589 if( *p - start < (int) size + 1 )
590 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
591
592 len = size;
593 (*p) -= len;
594 memcpy( *p, sig, len );
595
596 *--(*p) = 0;
597 len += 1;
598
599 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
600 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
601
602 // Write OID
603 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200604 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid,
605 strlen( oid ) ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000606
607 return( len );
608}
609
Paul Bakker9397dcb2013-09-06 09:55:26 +0200610static int x509_write_time( unsigned char **p, unsigned char *start,
611 const char *time, size_t size )
612{
613 int ret;
614 size_t len = 0;
615
Paul Bakker9c208aa2013-09-08 15:44:31 +0200616 /*
617 * write ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
618 */
619 if( time[0] == '2' && time[1] == '0' && time [2] < '5' )
620 {
621 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
622 (const unsigned char *) time + 2,
623 size - 2 ) );
624 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
625 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_UTC_TIME ) );
626 }
627 else
628 {
629 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
630 (const unsigned char *) time,
631 size ) );
632 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
633 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_GENERALIZED_TIME ) );
634 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200635
636 return( len );
637}
638
Paul Bakker15162a02013-09-06 19:27:21 +0200639static int x509_write_extension( unsigned char **p, unsigned char *start,
640 asn1_named_data *ext )
641{
642 int ret;
643 size_t len = 0;
644
645 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->val.p + 1,
646 ext->val.len - 1 ) );
647 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->val.len - 1 ) );
648 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) );
649
650 if( ext->val.p[0] != 0 )
651 {
652 ASN1_CHK_ADD( len, asn1_write_bool( p, start, 1 ) );
653 }
654
655 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->oid.p,
656 ext->oid.len ) );
657 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->oid.len ) );
658 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) );
659
660 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
661 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
662
663 return( len );
664}
665
666/*
667 * Extension ::= SEQUENCE {
668 * extnID OBJECT IDENTIFIER,
669 * critical BOOLEAN DEFAULT FALSE,
670 * extnValue OCTET STRING
671 * -- contains the DER encoding of an ASN.1 value
672 * -- corresponding to the extension type identified
673 * -- by extnID
674 * }
675 */
676static int x509_write_extensions( unsigned char **p, unsigned char *start,
677 asn1_named_data *first )
678{
679 int ret;
680 size_t len = 0;
681 asn1_named_data *cur_ext = first;
682
683 while( cur_ext != NULL )
684 {
685 ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
686 cur_ext = cur_ext->next;
687 }
688
689 return( len );
690}
691
Paul Bakkercd358032013-09-09 12:08:11 +0200692int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000693{
694 int ret;
Paul Bakkerc70b9822013-04-07 22:00:46 +0200695 const char *sig_oid;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000696 unsigned char *c, *c2;
Paul Bakker3cac5e02012-02-16 14:08:06 +0000697 unsigned char hash[64];
698 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000699 unsigned char tmp_buf[2048];
Paul Bakker9397dcb2013-09-06 09:55:26 +0200700 size_t pub_len = 0, sig_len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000701 size_t len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000702
703 c = tmp_buf + 2048 - 1;
704
Paul Bakker15162a02013-09-06 19:27:21 +0200705 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200706
Paul Bakkere5eae762013-08-26 12:05:14 +0200707 if( len )
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_SEQUENCE ) );
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_SET ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200714
Paul Bakker5f45e622013-09-09 12:02:36 +0200715 ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ,
716 OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200717
Paul Bakkere5eae762013-08-26 12:05:14 +0200718 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 Bakkerfde42702013-08-25 14:47:27 +0200720 }
721
Paul Bakkere5eae762013-08-26 12:05:14 +0200722 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000723 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) );
724
Paul Bakker8eabfc12013-08-25 10:18:25 +0200725 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->rsa->E ) );
726 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->rsa->N ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000727
728 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
729 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
730
731 if( c - tmp_buf < 1 )
732 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
733
Paul Bakker8eabfc12013-08-25 10:18:25 +0200734 /*
735 * AlgorithmIdentifier ::= SEQUENCE {
736 * algorithm OBJECT IDENTIFIER,
737 * parameters ANY DEFINED BY algorithm OPTIONAL }
738 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000739 *--c = 0;
740 pub_len += 1;
741
742 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
743 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_BIT_STRING ) );
744
Paul Bakker5f45e622013-09-09 12:02:36 +0200745 ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf,
746 OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000747
748 len += pub_len;
749 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) );
750 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
751
Paul Bakker9397dcb2013-09-06 09:55:26 +0200752 /*
753 * Subject ::= Name
754 */
755 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000756
Paul Bakker8eabfc12013-08-25 10:18:25 +0200757 /*
758 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
759 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000760 ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
761
762 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
763 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200764
Paul Bakker8eabfc12013-08-25 10:18:25 +0200765 md( md_info_from_type( ctx->md_alg ), c, len, hash );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000766
Paul Bakker8eabfc12013-08-25 10:18:25 +0200767 rsa_pkcs1_sign( ctx->rsa, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000768
769 // Generate correct OID
770 //
Paul Bakker8eabfc12013-08-25 10:18:25 +0200771 ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000772
773 c2 = buf + size - 1;
Paul Bakker8eabfc12013-08-25 10:18:25 +0200774 ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig, ctx->rsa->len ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200775
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000776 c2 -= len;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200777 memcpy( c2, c, len );
778
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000779 len += sig_len;
780 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
781 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
782
783 return( len );
784}
785
Paul Bakker9397dcb2013-09-06 09:55:26 +0200786int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size )
787{
788 int ret;
789 const char *sig_oid;
790 unsigned char *c, *c2;
791 unsigned char hash[64];
792 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
793 unsigned char tmp_buf[2048];
794 size_t sub_len = 0, pub_len = 0, sig_len = 0;
795 size_t len = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200796
797 c = tmp_buf + 2048 - 1;
798
799 // Generate correct OID
800 //
801 ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid );
802 if( ret != 0 )
803 return( ret );
804
Paul Bakker15162a02013-09-06 19:27:21 +0200805 /*
806 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
807 */
808 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
809 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
810 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
811 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
812 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200813
814 /*
815 * SubjectPublicKeyInfo ::= SEQUENCE {
816 * algorithm AlgorithmIdentifier,
817 * subjectPublicKey BIT STRING }
818 */
819 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->subject_key->E ) );
820 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->subject_key->N ) );
821
822 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
823 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
824
825 if( c - tmp_buf < 1 )
826 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
827
828 *--c = 0;
829 pub_len += 1;
830
831 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
832 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_BIT_STRING ) );
833
Paul Bakker5f45e622013-09-09 12:02:36 +0200834 ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf,
835 OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200836
837 len += pub_len;
838 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) );
839 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
840
841 /*
842 * Subject ::= Name
843 */
844 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
845
846 /*
847 * Validity ::= SEQUENCE {
848 * notBefore Time,
849 * notAfter Time }
850 */
851 sub_len = 0;
852
853 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
854 X509_RFC5280_UTC_TIME_LEN ) );
855
856 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
857 X509_RFC5280_UTC_TIME_LEN ) );
858
859 len += sub_len;
860 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
861 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
862
863 /*
864 * Issuer ::= Name
865 */
866 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->issuer ) );
867
868 /*
869 * Signature ::= AlgorithmIdentifier
870 */
871 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf,
Paul Bakker5f45e622013-09-09 12:02:36 +0200872 sig_oid, strlen( sig_oid ) ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200873
874 /*
875 * Serial ::= INTEGER
876 */
877 ASN1_CHK_ADD( len, asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
878
879 /*
880 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
881 */
882 sub_len = 0;
883 ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) );
884 len += sub_len;
885 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
886 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) );
887
888 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
889 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
890
891 md( md_info_from_type( ctx->md_alg ), c, len, hash );
892
893 rsa_pkcs1_sign( ctx->issuer_key, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig );
894
895 c2 = buf + size - 1;
896 ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig, ctx->issuer_key->len ) );
897
898 c2 -= len;
899 memcpy( c2, c, len );
900
901 len += sig_len;
902 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
903 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
904
905 return( len );
906}
907
908#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
909#define PEM_END_CRT "-----END CERTIFICATE-----\n"
910
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200911#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n"
912#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n"
913
914#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n"
915#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n"
916
917#define PEM_BEGIN_PRIVATE_KEY "-----BEGIN RSA PRIVATE KEY-----\n"
918#define PEM_END_PRIVATE_KEY "-----END RSA PRIVATE KEY-----\n"
Paul Bakker135f1e92013-08-26 16:54:13 +0200919
920#if defined(POLARSSL_BASE64_C)
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200921static int x509write_pemify( const char *begin_str, const char *end_str,
922 const unsigned char *der_data, size_t der_len,
923 unsigned char *buf, size_t size )
Paul Bakker135f1e92013-08-26 16:54:13 +0200924{
925 int ret;
Paul Bakker135f1e92013-08-26 16:54:13 +0200926 unsigned char base_buf[4096];
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200927 unsigned char *c = base_buf, *p = buf;
928 size_t len = 0, olen = sizeof(base_buf);
Paul Bakker135f1e92013-08-26 16:54:13 +0200929
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200930 if( ( ret = base64_encode( base_buf, &olen, der_data, der_len ) ) != 0 )
Paul Bakker135f1e92013-08-26 16:54:13 +0200931 return( ret );
932
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200933 if( olen + strlen( begin_str ) + strlen( end_str ) +
Paul Bakker135f1e92013-08-26 16:54:13 +0200934 olen / 64 > size )
935 {
936 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
937 }
938
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200939 memcpy( p, begin_str, strlen( begin_str ) );
940 p += strlen( begin_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200941
942 while( olen )
943 {
944 len = ( olen > 64 ) ? 64 : olen;
945 memcpy( p, c, len );
946 olen -= len;
947 p += len;
948 c += len;
949 *p++ = '\n';
950 }
951
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200952 memcpy( p, end_str, strlen( end_str ) );
953 p += strlen( end_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200954
955 *p = '\0';
956
957 return( 0 );
958}
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200959
Paul Bakker9397dcb2013-09-06 09:55:26 +0200960int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size )
961{
962 int ret;
963 unsigned char output_buf[4096];
964
965 if( ( ret = x509write_crt_der( crt, output_buf,
966 sizeof(output_buf) ) ) < 0 )
967 {
968 return( ret );
969 }
970
971 if( ( ret = x509write_pemify( PEM_BEGIN_CRT, PEM_END_CRT,
972 output_buf + sizeof(output_buf) - 1 - ret,
973 ret, buf, size ) ) != 0 )
974 {
975 return( ret );
976 }
977
978 return( 0 );
979}
980
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200981int x509write_pubkey_pem( rsa_context *rsa, unsigned char *buf, size_t size )
982{
983 int ret;
984 unsigned char output_buf[4096];
985
986 if( ( ret = x509write_pubkey_der( rsa, output_buf,
987 sizeof(output_buf) ) ) < 0 )
988 {
989 return( ret );
990 }
991
992 if( ( ret = x509write_pemify( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
993 output_buf + sizeof(output_buf) - 1 - ret,
994 ret, buf, size ) ) != 0 )
995 {
996 return( ret );
997 }
998
999 return( 0 );
1000}
1001
1002int x509write_key_pem( rsa_context *rsa, unsigned char *buf, size_t size )
1003{
1004 int ret;
1005 unsigned char output_buf[4096];
1006
1007 if( ( ret = x509write_key_der( rsa, output_buf,
1008 sizeof(output_buf) ) ) < 0 )
1009 {
1010 return( ret );
1011 }
1012
1013 if( ( ret = x509write_pemify( PEM_BEGIN_PRIVATE_KEY, PEM_END_PRIVATE_KEY,
1014 output_buf + sizeof(output_buf) - 1 - ret,
1015 ret, buf, size ) ) != 0 )
1016 {
1017 return( ret );
1018 }
1019
1020 return( 0 );
1021}
1022
Paul Bakkercd358032013-09-09 12:08:11 +02001023int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size )
Paul Bakkerf3df61a2013-08-26 17:22:23 +02001024{
1025 int ret;
1026 unsigned char output_buf[4096];
1027
1028 if( ( ret = x509write_csr_der( ctx, output_buf,
1029 sizeof(output_buf) ) ) < 0 )
1030 {
1031 return( ret );
1032 }
1033
1034 if( ( ret = x509write_pemify( PEM_BEGIN_CSR, PEM_END_CSR,
1035 output_buf + sizeof(output_buf) - 1 - ret,
1036 ret, buf, size ) ) != 0 )
1037 {
1038 return( ret );
1039 }
1040
1041 return( 0 );
1042}
Paul Bakker135f1e92013-08-26 16:54:13 +02001043#endif /* POLARSSL_BASE64_C */
1044
Paul Bakkerbdb912d2012-02-13 23:11:30 +00001045#endif