blob: f4f3c4dcce41ed058a37a920c6c0e24528599b5b [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,
Paul Bakker1c3853b2013-09-10 11:43:44 +0200584 const char *oid, size_t oid_len,
585 unsigned char *sig, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000586{
587 int ret;
588 size_t len = 0;
589
590 if( *p - start < (int) size + 1 )
591 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
592
593 len = size;
594 (*p) -= len;
595 memcpy( *p, sig, len );
596
597 *--(*p) = 0;
598 len += 1;
599
600 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
601 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
602
603 // Write OID
604 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200605 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid,
Paul Bakker1c3853b2013-09-10 11:43:44 +0200606 oid_len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000607
608 return( len );
609}
610
Paul Bakker9397dcb2013-09-06 09:55:26 +0200611static int x509_write_time( unsigned char **p, unsigned char *start,
612 const char *time, size_t size )
613{
614 int ret;
615 size_t len = 0;
616
Paul Bakker9c208aa2013-09-08 15:44:31 +0200617 /*
618 * write ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
619 */
620 if( time[0] == '2' && time[1] == '0' && time [2] < '5' )
621 {
622 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
623 (const unsigned char *) time + 2,
624 size - 2 ) );
625 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
626 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_UTC_TIME ) );
627 }
628 else
629 {
630 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
631 (const unsigned char *) time,
632 size ) );
633 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
634 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_GENERALIZED_TIME ) );
635 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200636
637 return( len );
638}
639
Paul Bakker15162a02013-09-06 19:27:21 +0200640static int x509_write_extension( unsigned char **p, unsigned char *start,
641 asn1_named_data *ext )
642{
643 int ret;
644 size_t len = 0;
645
646 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->val.p + 1,
647 ext->val.len - 1 ) );
648 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->val.len - 1 ) );
649 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) );
650
651 if( ext->val.p[0] != 0 )
652 {
653 ASN1_CHK_ADD( len, asn1_write_bool( p, start, 1 ) );
654 }
655
656 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->oid.p,
657 ext->oid.len ) );
658 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->oid.len ) );
659 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) );
660
661 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
662 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
663
664 return( len );
665}
666
667/*
668 * Extension ::= SEQUENCE {
669 * extnID OBJECT IDENTIFIER,
670 * critical BOOLEAN DEFAULT FALSE,
671 * extnValue OCTET STRING
672 * -- contains the DER encoding of an ASN.1 value
673 * -- corresponding to the extension type identified
674 * -- by extnID
675 * }
676 */
677static int x509_write_extensions( unsigned char **p, unsigned char *start,
678 asn1_named_data *first )
679{
680 int ret;
681 size_t len = 0;
682 asn1_named_data *cur_ext = first;
683
684 while( cur_ext != NULL )
685 {
686 ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
687 cur_ext = cur_ext->next;
688 }
689
690 return( len );
691}
692
Paul Bakkercd358032013-09-09 12:08:11 +0200693int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000694{
695 int ret;
Paul Bakkerc70b9822013-04-07 22:00:46 +0200696 const char *sig_oid;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200697 size_t sig_oid_len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000698 unsigned char *c, *c2;
Paul Bakker3cac5e02012-02-16 14:08:06 +0000699 unsigned char hash[64];
700 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000701 unsigned char tmp_buf[2048];
Paul Bakker9397dcb2013-09-06 09:55:26 +0200702 size_t pub_len = 0, sig_len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000703 size_t len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000704
705 c = tmp_buf + 2048 - 1;
706
Paul Bakker15162a02013-09-06 19:27:21 +0200707 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200708
Paul Bakkere5eae762013-08-26 12:05:14 +0200709 if( len )
Paul Bakkerfde42702013-08-25 14:47:27 +0200710 {
Paul Bakkere5eae762013-08-26 12:05:14 +0200711 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
712 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
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_SET ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200716
Paul Bakker5f45e622013-09-09 12:02:36 +0200717 ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ,
718 OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200719
Paul Bakkere5eae762013-08-26 12:05:14 +0200720 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
721 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200722 }
723
Paul Bakkere5eae762013-08-26 12:05:14 +0200724 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000725 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) );
726
Paul Bakker8eabfc12013-08-25 10:18:25 +0200727 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->rsa->E ) );
728 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->rsa->N ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000729
730 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
731 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
732
733 if( c - tmp_buf < 1 )
734 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
735
Paul Bakker8eabfc12013-08-25 10:18:25 +0200736 /*
737 * AlgorithmIdentifier ::= SEQUENCE {
738 * algorithm OBJECT IDENTIFIER,
739 * parameters ANY DEFINED BY algorithm OPTIONAL }
740 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000741 *--c = 0;
742 pub_len += 1;
743
744 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
745 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_BIT_STRING ) );
746
Paul Bakker5f45e622013-09-09 12:02:36 +0200747 ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf,
748 OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000749
750 len += pub_len;
751 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) );
752 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
753
Paul Bakker9397dcb2013-09-06 09:55:26 +0200754 /*
755 * Subject ::= Name
756 */
757 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000758
Paul Bakker8eabfc12013-08-25 10:18:25 +0200759 /*
760 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
761 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000762 ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
763
764 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
765 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200766
Paul Bakker8eabfc12013-08-25 10:18:25 +0200767 md( md_info_from_type( ctx->md_alg ), c, len, hash );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000768
Paul Bakker8eabfc12013-08-25 10:18:25 +0200769 rsa_pkcs1_sign( ctx->rsa, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000770
771 // Generate correct OID
772 //
Paul Bakker1c3853b2013-09-10 11:43:44 +0200773 ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid,
774 &sig_oid_len );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000775
776 c2 = buf + size - 1;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200777 ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len,
778 sig, ctx->rsa->len ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200779
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000780 c2 -= len;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200781 memcpy( c2, c, len );
782
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000783 len += sig_len;
784 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
785 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
786
787 return( len );
788}
789
Paul Bakker9397dcb2013-09-06 09:55:26 +0200790int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size )
791{
792 int ret;
793 const char *sig_oid;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200794 size_t sig_oid_len = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200795 unsigned char *c, *c2;
796 unsigned char hash[64];
797 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
798 unsigned char tmp_buf[2048];
799 size_t sub_len = 0, pub_len = 0, sig_len = 0;
800 size_t len = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200801
802 c = tmp_buf + 2048 - 1;
803
804 // Generate correct OID
805 //
Paul Bakker1c3853b2013-09-10 11:43:44 +0200806 ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid,
807 &sig_oid_len );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200808 if( ret != 0 )
809 return( ret );
810
Paul Bakker15162a02013-09-06 19:27:21 +0200811 /*
812 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
813 */
814 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
815 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
816 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
817 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
818 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200819
820 /*
821 * SubjectPublicKeyInfo ::= SEQUENCE {
822 * algorithm AlgorithmIdentifier,
823 * subjectPublicKey BIT STRING }
824 */
825 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->subject_key->E ) );
826 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->subject_key->N ) );
827
828 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
829 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
830
831 if( c - tmp_buf < 1 )
832 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
833
834 *--c = 0;
835 pub_len += 1;
836
837 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
838 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_BIT_STRING ) );
839
Paul Bakker5f45e622013-09-09 12:02:36 +0200840 ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf,
841 OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200842
843 len += pub_len;
844 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) );
845 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
846
847 /*
848 * Subject ::= Name
849 */
850 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
851
852 /*
853 * Validity ::= SEQUENCE {
854 * notBefore Time,
855 * notAfter Time }
856 */
857 sub_len = 0;
858
859 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
860 X509_RFC5280_UTC_TIME_LEN ) );
861
862 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
863 X509_RFC5280_UTC_TIME_LEN ) );
864
865 len += sub_len;
866 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
867 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
868
869 /*
870 * Issuer ::= Name
871 */
872 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->issuer ) );
873
874 /*
875 * Signature ::= AlgorithmIdentifier
876 */
877 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf,
Paul Bakker5f45e622013-09-09 12:02:36 +0200878 sig_oid, strlen( sig_oid ) ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200879
880 /*
881 * Serial ::= INTEGER
882 */
883 ASN1_CHK_ADD( len, asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
884
885 /*
886 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
887 */
888 sub_len = 0;
889 ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) );
890 len += sub_len;
891 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
892 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) );
893
894 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
895 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
896
897 md( md_info_from_type( ctx->md_alg ), c, len, hash );
898
899 rsa_pkcs1_sign( ctx->issuer_key, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig );
900
901 c2 = buf + size - 1;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200902 ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len,
903 sig, ctx->issuer_key->len ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200904
905 c2 -= len;
906 memcpy( c2, c, len );
907
908 len += sig_len;
909 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
910 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
911
912 return( len );
913}
914
915#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
916#define PEM_END_CRT "-----END CERTIFICATE-----\n"
917
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200918#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n"
919#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n"
920
921#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n"
922#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n"
923
924#define PEM_BEGIN_PRIVATE_KEY "-----BEGIN RSA PRIVATE KEY-----\n"
925#define PEM_END_PRIVATE_KEY "-----END RSA PRIVATE KEY-----\n"
Paul Bakker135f1e92013-08-26 16:54:13 +0200926
927#if defined(POLARSSL_BASE64_C)
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200928static int x509write_pemify( const char *begin_str, const char *end_str,
929 const unsigned char *der_data, size_t der_len,
930 unsigned char *buf, size_t size )
Paul Bakker135f1e92013-08-26 16:54:13 +0200931{
932 int ret;
Paul Bakker135f1e92013-08-26 16:54:13 +0200933 unsigned char base_buf[4096];
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200934 unsigned char *c = base_buf, *p = buf;
935 size_t len = 0, olen = sizeof(base_buf);
Paul Bakker135f1e92013-08-26 16:54:13 +0200936
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200937 if( ( ret = base64_encode( base_buf, &olen, der_data, der_len ) ) != 0 )
Paul Bakker135f1e92013-08-26 16:54:13 +0200938 return( ret );
939
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200940 if( olen + strlen( begin_str ) + strlen( end_str ) +
Paul Bakker135f1e92013-08-26 16:54:13 +0200941 olen / 64 > size )
942 {
943 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
944 }
945
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200946 memcpy( p, begin_str, strlen( begin_str ) );
947 p += strlen( begin_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200948
949 while( olen )
950 {
951 len = ( olen > 64 ) ? 64 : olen;
952 memcpy( p, c, len );
953 olen -= len;
954 p += len;
955 c += len;
956 *p++ = '\n';
957 }
958
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200959 memcpy( p, end_str, strlen( end_str ) );
960 p += strlen( end_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200961
962 *p = '\0';
963
964 return( 0 );
965}
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200966
Paul Bakker9397dcb2013-09-06 09:55:26 +0200967int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size )
968{
969 int ret;
970 unsigned char output_buf[4096];
971
972 if( ( ret = x509write_crt_der( crt, output_buf,
973 sizeof(output_buf) ) ) < 0 )
974 {
975 return( ret );
976 }
977
978 if( ( ret = x509write_pemify( PEM_BEGIN_CRT, PEM_END_CRT,
979 output_buf + sizeof(output_buf) - 1 - ret,
980 ret, buf, size ) ) != 0 )
981 {
982 return( ret );
983 }
984
985 return( 0 );
986}
987
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200988int x509write_pubkey_pem( rsa_context *rsa, unsigned char *buf, size_t size )
989{
990 int ret;
991 unsigned char output_buf[4096];
992
993 if( ( ret = x509write_pubkey_der( rsa, output_buf,
994 sizeof(output_buf) ) ) < 0 )
995 {
996 return( ret );
997 }
998
999 if( ( ret = x509write_pemify( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
1000 output_buf + sizeof(output_buf) - 1 - ret,
1001 ret, buf, size ) ) != 0 )
1002 {
1003 return( ret );
1004 }
1005
1006 return( 0 );
1007}
1008
1009int x509write_key_pem( rsa_context *rsa, unsigned char *buf, size_t size )
1010{
1011 int ret;
1012 unsigned char output_buf[4096];
1013
1014 if( ( ret = x509write_key_der( rsa, output_buf,
1015 sizeof(output_buf) ) ) < 0 )
1016 {
1017 return( ret );
1018 }
1019
1020 if( ( ret = x509write_pemify( PEM_BEGIN_PRIVATE_KEY, PEM_END_PRIVATE_KEY,
1021 output_buf + sizeof(output_buf) - 1 - ret,
1022 ret, buf, size ) ) != 0 )
1023 {
1024 return( ret );
1025 }
1026
1027 return( 0 );
1028}
1029
Paul Bakkercd358032013-09-09 12:08:11 +02001030int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size )
Paul Bakkerf3df61a2013-08-26 17:22:23 +02001031{
1032 int ret;
1033 unsigned char output_buf[4096];
1034
1035 if( ( ret = x509write_csr_der( ctx, output_buf,
1036 sizeof(output_buf) ) ) < 0 )
1037 {
1038 return( ret );
1039 }
1040
1041 if( ( ret = x509write_pemify( PEM_BEGIN_CSR, PEM_END_CSR,
1042 output_buf + sizeof(output_buf) - 1 - ret,
1043 ret, buf, size ) ) != 0 )
1044 {
1045 return( ret );
1046 }
1047
1048 return( 0 );
1049}
Paul Bakker135f1e92013-08-26 16:54:13 +02001050#endif /* POLARSSL_BASE64_C */
1051
Paul Bakkerbdb912d2012-02-13 23:11:30 +00001052#endif