blob: 643538885275406ed8d770c8c3aab1396f9fd611 [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
Paul Bakkercd358032013-09-09 12:08:11 +0200152void x509write_csr_set_rsa_key( x509write_csr *ctx, rsa_context *rsa )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200153{
154 ctx->rsa = rsa;
155}
156
Paul Bakkercd358032013-09-09 12:08:11 +0200157int x509write_csr_set_subject_name( x509write_csr *ctx, char *subject_name )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200158{
159 return x509write_string_to_names( &ctx->subject, subject_name );
160}
161
Paul Bakker15162a02013-09-06 19:27:21 +0200162/* The first byte of the value in the asn1_named_data structure is reserved
163 * to store the critical boolean for us
164 */
165static int x509_set_extension( asn1_named_data **head,
166 const char *oid, size_t oid_len,
167 int critical,
168 const unsigned char *val, size_t val_len )
Paul Bakkerfde42702013-08-25 14:47:27 +0200169{
Paul Bakkere5eae762013-08-26 12:05:14 +0200170 asn1_named_data *cur;
Paul Bakkere5eae762013-08-26 12:05:14 +0200171
Paul Bakker59ba59f2013-09-09 11:26:00 +0200172 if( ( cur = asn1_store_named_data( head, oid, oid_len,
173 NULL, val_len + 1 ) ) == NULL )
Paul Bakkere5eae762013-08-26 12:05:14 +0200174 {
Paul Bakker59ba59f2013-09-09 11:26:00 +0200175 return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
Paul Bakker1c0e5502013-08-26 13:41:01 +0200176 }
177
Paul Bakker15162a02013-09-06 19:27:21 +0200178 cur->val.p[0] = critical;
179 memcpy( cur->val.p + 1, val, val_len );
Paul Bakker1c0e5502013-08-26 13:41:01 +0200180
181 return( 0 );
182}
183
Paul Bakkercd358032013-09-09 12:08:11 +0200184int x509write_csr_set_extension( x509write_csr *ctx,
Paul Bakker15162a02013-09-06 19:27:21 +0200185 const char *oid, size_t oid_len,
186 const unsigned char *val, size_t val_len )
187{
188 return x509_set_extension( &ctx->extensions, oid, oid_len,
189 0, val, val_len );
190}
191
Paul Bakkercd358032013-09-09 12:08:11 +0200192int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200193{
194 unsigned char buf[4];
195 unsigned char *c;
196 int ret;
197
198 c = buf + 4;
199
Paul Bakker624d03a2013-08-26 14:12:57 +0200200 if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200201 return( ret );
202
203 ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE,
204 OID_SIZE( OID_KEY_USAGE ),
205 buf, 4 );
206 if( ret != 0 )
207 return( ret );
208
209 return( 0 );
210}
211
Paul Bakkercd358032013-09-09 12:08:11 +0200212int x509write_csr_set_ns_cert_type( x509write_csr *ctx,
213 unsigned char ns_cert_type )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200214{
215 unsigned char buf[4];
216 unsigned char *c;
217 int ret;
218
219 c = buf + 4;
220
221 if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
222 return( ret );
223
224 ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE,
225 OID_SIZE( OID_NS_CERT_TYPE ),
226 buf, 4 );
227 if( ret != 0 )
228 return( ret );
Paul Bakkere5eae762013-08-26 12:05:14 +0200229
230 return( 0 );
Paul Bakkerfde42702013-08-25 14:47:27 +0200231}
232
Paul Bakker9397dcb2013-09-06 09:55:26 +0200233void x509write_crt_init( x509write_cert *ctx )
234{
235 memset( ctx, 0, sizeof(x509write_cert) );
236
237 mpi_init( &ctx->serial );
238 ctx->version = X509_CRT_VERSION_3;
239}
240
241void x509write_crt_free( x509write_cert *ctx )
242{
Paul Bakker9397dcb2013-09-06 09:55:26 +0200243 mpi_free( &ctx->serial );
244
Paul Bakker5f45e622013-09-09 12:02:36 +0200245 asn1_free_named_data_list( &ctx->subject );
246 asn1_free_named_data_list( &ctx->issuer );
247 asn1_free_named_data_list( &ctx->extensions );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200248
Paul Bakkercd358032013-09-09 12:08:11 +0200249 memset( ctx, 0, sizeof(x509write_csr) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200250}
251
252void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg )
253{
254 ctx->md_alg = md_alg;
255}
256
257void x509write_crt_set_subject_key( x509write_cert *ctx, rsa_context *rsa )
258{
259 ctx->subject_key = rsa;
260}
261
262void x509write_crt_set_issuer_key( x509write_cert *ctx, rsa_context *rsa )
263{
264 ctx->issuer_key = rsa;
265}
266
267int x509write_crt_set_subject_name( x509write_cert *ctx, char *subject_name )
268{
269 return x509write_string_to_names( &ctx->subject, subject_name );
270}
271
272int x509write_crt_set_issuer_name( x509write_cert *ctx, char *issuer_name )
273{
274 return x509write_string_to_names( &ctx->issuer, issuer_name );
275}
276
277int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial )
278{
279 int ret;
280
281 if( ( ret = mpi_copy( &ctx->serial, serial ) ) != 0 )
282 return( ret );
283
284 return( 0 );
285}
286
287int x509write_crt_set_validity( x509write_cert *ctx, char *not_before,
288 char *not_after )
289{
290 if( strlen(not_before) != X509_RFC5280_UTC_TIME_LEN - 1 ||
291 strlen(not_after) != X509_RFC5280_UTC_TIME_LEN - 1 )
292 {
293 return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
294 }
295 strncpy( ctx->not_before, not_before, X509_RFC5280_UTC_TIME_LEN );
296 strncpy( ctx->not_after , not_after , X509_RFC5280_UTC_TIME_LEN );
297 ctx->not_before[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
298 ctx->not_after[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
299
300 return( 0 );
301}
302
Paul Bakker15162a02013-09-06 19:27:21 +0200303int x509write_crt_set_extension( x509write_cert *ctx,
304 const char *oid, size_t oid_len,
305 int critical,
306 const unsigned char *val, size_t val_len )
307{
308 return x509_set_extension( &ctx->extensions, oid, oid_len,
309 critical, val, val_len );
310}
311
312int x509write_crt_set_basic_constraints( x509write_cert *ctx,
313 int is_ca, int max_pathlen )
314{
315 int ret;
316 unsigned char buf[9];
317 unsigned char *c = buf + sizeof(buf);
318 size_t len = 0;
319
320 memset( buf, 0, sizeof(buf) );
321
322 if( is_ca && max_pathlen > 127 )
323 return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
324
325 if( is_ca )
326 {
327 if( max_pathlen >= 0 )
328 {
329 ASN1_CHK_ADD( len, asn1_write_int( &c, buf, max_pathlen ) );
330 }
331 ASN1_CHK_ADD( len, asn1_write_bool( &c, buf, 1 ) );
332 }
333
334 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
335 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
336
337 return x509write_crt_set_extension( ctx, OID_BASIC_CONSTRAINTS,
338 OID_SIZE( OID_BASIC_CONSTRAINTS ),
339 0, buf + sizeof(buf) - len, len );
340}
341
342int x509write_crt_set_subject_key_identifier( x509write_cert *ctx )
343{
344 int ret;
345 unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
346 unsigned char *c = buf + sizeof(buf);
347 size_t len = 0;
348
349 memset( buf, 0, sizeof(buf));
350 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, ctx->subject_key ) );
351
352 sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
353 c = buf + sizeof(buf) - 20;
354 len = 20;
355
356 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
357 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_OCTET_STRING ) );
358
359 return x509write_crt_set_extension( ctx, OID_SUBJECT_KEY_IDENTIFIER,
360 OID_SIZE( OID_SUBJECT_KEY_IDENTIFIER ),
361 0, buf + sizeof(buf) - len, len );
362}
363
364int x509write_crt_set_authority_key_identifier( x509write_cert *ctx )
365{
366 int ret;
367 unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
368 unsigned char *c = buf + sizeof(buf);
369 size_t len = 0;
370
371 memset( buf, 0, sizeof(buf));
372 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, ctx->issuer_key ) );
373
374 sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
375 c = buf + sizeof(buf) - 20;
376 len = 20;
377
378 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
379 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONTEXT_SPECIFIC | 0 ) );
380
381 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
382 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
383
384 return x509write_crt_set_extension( ctx, OID_AUTHORITY_KEY_IDENTIFIER,
385 OID_SIZE( OID_AUTHORITY_KEY_IDENTIFIER ),
386 0, buf + sizeof(buf) - len, len );
387}
388
Paul Bakker52be08c2013-09-09 12:37:54 +0200389int x509write_crt_set_key_usage( x509write_cert *ctx, unsigned char key_usage )
390{
391 unsigned char buf[4];
392 unsigned char *c;
393 int ret;
394
395 c = buf + 4;
396
397 if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
398 return( ret );
399
400 ret = x509write_crt_set_extension( ctx, OID_KEY_USAGE,
401 OID_SIZE( OID_KEY_USAGE ),
402 1, buf, 4 );
403 if( ret != 0 )
404 return( ret );
405
406 return( 0 );
407}
408
409int x509write_crt_set_ns_cert_type( x509write_cert *ctx,
410 unsigned char ns_cert_type )
411{
412 unsigned char buf[4];
413 unsigned char *c;
414 int ret;
415
416 c = buf + 4;
417
418 if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
419 return( ret );
420
421 ret = x509write_crt_set_extension( ctx, OID_NS_CERT_TYPE,
422 OID_SIZE( OID_NS_CERT_TYPE ),
423 0, buf, 4 );
424 if( ret != 0 )
425 return( ret );
426
427 return( 0 );
428}
429
Paul Bakker82e29452013-08-25 11:01:31 +0200430int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000431{
432 int ret;
433 unsigned char *c;
434 size_t len = 0;
435
436 c = buf + size - 1;
437
Paul Bakker15162a02013-09-06 19:27:21 +0200438 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, rsa ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000439
440 if( c - buf < 1 )
441 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
442
Paul Bakker8eabfc12013-08-25 10:18:25 +0200443 /*
444 * SubjectPublicKeyInfo ::= SEQUENCE {
445 * algorithm AlgorithmIdentifier,
446 * subjectPublicKey BIT STRING }
447 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000448 *--c = 0;
449 len += 1;
450
451 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
452 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) );
453
Paul Bakker5f45e622013-09-09 12:02:36 +0200454 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf,
455 OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000456
457 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
458 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
459
460 return( len );
461}
462
Paul Bakker82e29452013-08-25 11:01:31 +0200463int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000464{
465 int ret;
466 unsigned char *c;
467 size_t len = 0;
468
469 c = buf + size - 1;
470
471 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) );
472 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) );
473 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) );
474 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) );
475 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) );
476 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) );
477 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) );
478 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) );
479 ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) );
480
481 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
482 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
483
484 // TODO: Make NON RSA Specific variant later on
485/* *--c = 0;
486 len += 1;
487
488 len += asn1_write_len( &c, len);
489 len += asn1_write_tag( &c, ASN1_BIT_STRING );
490
491 len += asn1_write_oid( &c, OID_PKCS1_RSA );
492
493 len += asn1_write_int( &c, 0 );
494
495 len += asn1_write_len( &c, len);
496 len += asn1_write_tag( &c, ASN1_CONSTRUCTED | ASN1_SEQUENCE );*/
497
498/* for(i = 0; i < len; ++i)
499 {
500 if (i % 16 == 0 ) printf("\n");
501 printf("%02x ", c[i]);
502 }
503 printf("\n");*/
504
505 return( len );
506}
507
Paul Bakker9397dcb2013-09-06 09:55:26 +0200508/*
509 * RelativeDistinguishedName ::=
510 * SET OF AttributeTypeAndValue
511 *
512 * AttributeTypeAndValue ::= SEQUENCE {
513 * type AttributeType,
514 * value AttributeValue }
515 *
516 * AttributeType ::= OBJECT IDENTIFIER
517 *
518 * AttributeValue ::= ANY DEFINED BY AttributeType
519 */
Paul Bakker5f45e622013-09-09 12:02:36 +0200520static int x509_write_name( unsigned char **p, unsigned char *start,
521 const char *oid, size_t oid_len,
522 const unsigned char *name, size_t name_len )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000523{
524 int ret;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000525 size_t len = 0;
526
Paul Bakker05888152012-02-16 10:26:57 +0000527 // Write PrintableString for all except OID_PKCS9_EMAIL
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000528 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200529 if( OID_SIZE( OID_PKCS9_EMAIL ) == oid_len &&
530 memcmp( oid, OID_PKCS9_EMAIL, oid_len ) == 0 )
Paul Bakker05888152012-02-16 10:26:57 +0000531 {
Paul Bakker5f45e622013-09-09 12:02:36 +0200532 ASN1_CHK_ADD( len, asn1_write_ia5_string( p, start,
533 (const char *) name,
534 name_len ) );
Paul Bakker05888152012-02-16 10:26:57 +0000535 }
536 else
Paul Bakker5f45e622013-09-09 12:02:36 +0200537 {
538 ASN1_CHK_ADD( len, asn1_write_printable_string( p, start,
539 (const char *) name,
540 name_len ) );
541 }
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000542
543 // Write OID
544 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200545 ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000546
Paul Bakker5f45e622013-09-09 12:02:36 +0200547 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000548 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
549
550 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
551 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) );
552
553 return( len );
554}
555
Paul Bakker9397dcb2013-09-06 09:55:26 +0200556static int x509_write_names( unsigned char **p, unsigned char *start,
Paul Bakker5f45e622013-09-09 12:02:36 +0200557 asn1_named_data *first )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200558{
559 int ret;
560 size_t len = 0;
Paul Bakker5f45e622013-09-09 12:02:36 +0200561 asn1_named_data *cur = first;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200562
563 while( cur != NULL )
564 {
Paul Bakker5f45e622013-09-09 12:02:36 +0200565 ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p,
566 cur->oid.len,
567 cur->val.p, cur->val.len ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200568 cur = cur->next;
569 }
570
571 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
572 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
573
574 return( len );
575}
576
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200577static int x509_write_sig( unsigned char **p, unsigned char *start,
Paul Bakker1c3853b2013-09-10 11:43:44 +0200578 const char *oid, size_t oid_len,
579 unsigned char *sig, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000580{
581 int ret;
582 size_t len = 0;
583
584 if( *p - start < (int) size + 1 )
585 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
586
587 len = size;
588 (*p) -= len;
589 memcpy( *p, sig, len );
590
591 *--(*p) = 0;
592 len += 1;
593
594 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
595 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
596
597 // Write OID
598 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200599 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid,
Paul Bakker1c3853b2013-09-10 11:43:44 +0200600 oid_len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000601
602 return( len );
603}
604
Paul Bakker9397dcb2013-09-06 09:55:26 +0200605static int x509_write_time( unsigned char **p, unsigned char *start,
606 const char *time, size_t size )
607{
608 int ret;
609 size_t len = 0;
610
Paul Bakker9c208aa2013-09-08 15:44:31 +0200611 /*
612 * write ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
613 */
614 if( time[0] == '2' && time[1] == '0' && time [2] < '5' )
615 {
616 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
617 (const unsigned char *) time + 2,
618 size - 2 ) );
619 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
620 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_UTC_TIME ) );
621 }
622 else
623 {
624 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
625 (const unsigned char *) time,
626 size ) );
627 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
628 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_GENERALIZED_TIME ) );
629 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200630
631 return( len );
632}
633
Paul Bakker15162a02013-09-06 19:27:21 +0200634static int x509_write_extension( unsigned char **p, unsigned char *start,
635 asn1_named_data *ext )
636{
637 int ret;
638 size_t len = 0;
639
640 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->val.p + 1,
641 ext->val.len - 1 ) );
642 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->val.len - 1 ) );
643 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) );
644
645 if( ext->val.p[0] != 0 )
646 {
647 ASN1_CHK_ADD( len, asn1_write_bool( p, start, 1 ) );
648 }
649
650 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->oid.p,
651 ext->oid.len ) );
652 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->oid.len ) );
653 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) );
654
655 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
656 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
657
658 return( len );
659}
660
661/*
662 * Extension ::= SEQUENCE {
663 * extnID OBJECT IDENTIFIER,
664 * critical BOOLEAN DEFAULT FALSE,
665 * extnValue OCTET STRING
666 * -- contains the DER encoding of an ASN.1 value
667 * -- corresponding to the extension type identified
668 * -- by extnID
669 * }
670 */
671static int x509_write_extensions( unsigned char **p, unsigned char *start,
672 asn1_named_data *first )
673{
674 int ret;
675 size_t len = 0;
676 asn1_named_data *cur_ext = first;
677
678 while( cur_ext != NULL )
679 {
680 ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
681 cur_ext = cur_ext->next;
682 }
683
684 return( len );
685}
686
Paul Bakkercd358032013-09-09 12:08:11 +0200687int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000688{
689 int ret;
Paul Bakkerc70b9822013-04-07 22:00:46 +0200690 const char *sig_oid;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200691 size_t sig_oid_len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000692 unsigned char *c, *c2;
Paul Bakker3cac5e02012-02-16 14:08:06 +0000693 unsigned char hash[64];
694 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000695 unsigned char tmp_buf[2048];
Paul Bakker9397dcb2013-09-06 09:55:26 +0200696 size_t pub_len = 0, sig_len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000697 size_t len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000698
699 c = tmp_buf + 2048 - 1;
700
Paul Bakker15162a02013-09-06 19:27:21 +0200701 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200702
Paul Bakkere5eae762013-08-26 12:05:14 +0200703 if( len )
Paul Bakkerfde42702013-08-25 14:47:27 +0200704 {
Paul Bakkere5eae762013-08-26 12:05:14 +0200705 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
706 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200707
Paul Bakkere5eae762013-08-26 12:05:14 +0200708 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
709 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200710
Paul Bakker5f45e622013-09-09 12:02:36 +0200711 ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ,
712 OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200713
Paul Bakkere5eae762013-08-26 12:05:14 +0200714 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
715 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200716 }
717
Paul Bakkere5eae762013-08-26 12:05:14 +0200718 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000719 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) );
720
Paul Bakker8eabfc12013-08-25 10:18:25 +0200721 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->rsa->E ) );
722 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->rsa->N ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000723
724 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
725 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
726
727 if( c - tmp_buf < 1 )
728 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
729
Paul Bakker8eabfc12013-08-25 10:18:25 +0200730 /*
731 * AlgorithmIdentifier ::= SEQUENCE {
732 * algorithm OBJECT IDENTIFIER,
733 * parameters ANY DEFINED BY algorithm OPTIONAL }
734 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000735 *--c = 0;
736 pub_len += 1;
737
738 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
739 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_BIT_STRING ) );
740
Paul Bakker5f45e622013-09-09 12:02:36 +0200741 ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf,
742 OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000743
744 len += pub_len;
745 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) );
746 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
747
Paul Bakker9397dcb2013-09-06 09:55:26 +0200748 /*
749 * Subject ::= Name
750 */
751 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000752
Paul Bakker8eabfc12013-08-25 10:18:25 +0200753 /*
754 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
755 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000756 ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
757
758 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
759 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200760
Paul Bakker8eabfc12013-08-25 10:18:25 +0200761 md( md_info_from_type( ctx->md_alg ), c, len, hash );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000762
Paul Bakker8eabfc12013-08-25 10:18:25 +0200763 rsa_pkcs1_sign( ctx->rsa, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000764
765 // Generate correct OID
766 //
Paul Bakker1c3853b2013-09-10 11:43:44 +0200767 ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid,
768 &sig_oid_len );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000769
770 c2 = buf + size - 1;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200771 ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len,
772 sig, ctx->rsa->len ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200773
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000774 c2 -= len;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200775 memcpy( c2, c, len );
776
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000777 len += sig_len;
778 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
779 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
780
781 return( len );
782}
783
Paul Bakker9397dcb2013-09-06 09:55:26 +0200784int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size )
785{
786 int ret;
787 const char *sig_oid;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200788 size_t sig_oid_len = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200789 unsigned char *c, *c2;
790 unsigned char hash[64];
791 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
792 unsigned char tmp_buf[2048];
793 size_t sub_len = 0, pub_len = 0, sig_len = 0;
794 size_t len = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200795
796 c = tmp_buf + 2048 - 1;
797
798 // Generate correct OID
799 //
Paul Bakker1c3853b2013-09-10 11:43:44 +0200800 ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid,
801 &sig_oid_len );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200802 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;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200896 ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len,
897 sig, ctx->issuer_key->len ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200898
899 c2 -= len;
900 memcpy( c2, c, len );
901
902 len += sig_len;
903 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
904 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
905
906 return( len );
907}
908
909#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
910#define PEM_END_CRT "-----END CERTIFICATE-----\n"
911
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200912#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n"
913#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n"
914
915#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n"
916#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n"
917
918#define PEM_BEGIN_PRIVATE_KEY "-----BEGIN RSA PRIVATE KEY-----\n"
919#define PEM_END_PRIVATE_KEY "-----END RSA PRIVATE KEY-----\n"
Paul Bakker135f1e92013-08-26 16:54:13 +0200920
921#if defined(POLARSSL_BASE64_C)
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200922static int x509write_pemify( const char *begin_str, const char *end_str,
923 const unsigned char *der_data, size_t der_len,
924 unsigned char *buf, size_t size )
Paul Bakker135f1e92013-08-26 16:54:13 +0200925{
926 int ret;
Paul Bakker135f1e92013-08-26 16:54:13 +0200927 unsigned char base_buf[4096];
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200928 unsigned char *c = base_buf, *p = buf;
929 size_t len = 0, olen = sizeof(base_buf);
Paul Bakker135f1e92013-08-26 16:54:13 +0200930
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200931 if( ( ret = base64_encode( base_buf, &olen, der_data, der_len ) ) != 0 )
Paul Bakker135f1e92013-08-26 16:54:13 +0200932 return( ret );
933
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200934 if( olen + strlen( begin_str ) + strlen( end_str ) +
Paul Bakker135f1e92013-08-26 16:54:13 +0200935 olen / 64 > size )
936 {
937 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
938 }
939
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200940 memcpy( p, begin_str, strlen( begin_str ) );
941 p += strlen( begin_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200942
943 while( olen )
944 {
945 len = ( olen > 64 ) ? 64 : olen;
946 memcpy( p, c, len );
947 olen -= len;
948 p += len;
949 c += len;
950 *p++ = '\n';
951 }
952
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200953 memcpy( p, end_str, strlen( end_str ) );
954 p += strlen( end_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200955
956 *p = '\0';
957
958 return( 0 );
959}
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200960
Paul Bakker9397dcb2013-09-06 09:55:26 +0200961int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size )
962{
963 int ret;
964 unsigned char output_buf[4096];
965
966 if( ( ret = x509write_crt_der( crt, output_buf,
967 sizeof(output_buf) ) ) < 0 )
968 {
969 return( ret );
970 }
971
972 if( ( ret = x509write_pemify( PEM_BEGIN_CRT, PEM_END_CRT,
973 output_buf + sizeof(output_buf) - 1 - ret,
974 ret, buf, size ) ) != 0 )
975 {
976 return( ret );
977 }
978
979 return( 0 );
980}
981
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200982int x509write_pubkey_pem( rsa_context *rsa, unsigned char *buf, size_t size )
983{
984 int ret;
985 unsigned char output_buf[4096];
986
987 if( ( ret = x509write_pubkey_der( rsa, output_buf,
988 sizeof(output_buf) ) ) < 0 )
989 {
990 return( ret );
991 }
992
993 if( ( ret = x509write_pemify( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
994 output_buf + sizeof(output_buf) - 1 - ret,
995 ret, buf, size ) ) != 0 )
996 {
997 return( ret );
998 }
999
1000 return( 0 );
1001}
1002
1003int x509write_key_pem( rsa_context *rsa, unsigned char *buf, size_t size )
1004{
1005 int ret;
1006 unsigned char output_buf[4096];
1007
1008 if( ( ret = x509write_key_der( rsa, output_buf,
1009 sizeof(output_buf) ) ) < 0 )
1010 {
1011 return( ret );
1012 }
1013
1014 if( ( ret = x509write_pemify( PEM_BEGIN_PRIVATE_KEY, PEM_END_PRIVATE_KEY,
1015 output_buf + sizeof(output_buf) - 1 - ret,
1016 ret, buf, size ) ) != 0 )
1017 {
1018 return( ret );
1019 }
1020
1021 return( 0 );
1022}
1023
Paul Bakkercd358032013-09-09 12:08:11 +02001024int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size )
Paul Bakkerf3df61a2013-08-26 17:22:23 +02001025{
1026 int ret;
1027 unsigned char output_buf[4096];
1028
1029 if( ( ret = x509write_csr_der( ctx, output_buf,
1030 sizeof(output_buf) ) ) < 0 )
1031 {
1032 return( ret );
1033 }
1034
1035 if( ( ret = x509write_pemify( PEM_BEGIN_CSR, PEM_END_CSR,
1036 output_buf + sizeof(output_buf) - 1 - ret,
1037 ret, buf, size ) ) != 0 )
1038 {
1039 return( ret );
1040 }
1041
1042 return( 0 );
1043}
Paul Bakker135f1e92013-08-26 16:54:13 +02001044#endif /* POLARSSL_BASE64_C */
1045
Paul Bakkerbdb912d2012-02-13 23:11:30 +00001046#endif