blob: 3aeb795265f60b04d39ea27b125c88299d3fd7c4 [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
Manuel Pégourié-Gonnardd4eb5b52013-09-11 18:16:20 +020026/*
27 * References:
28 * - certificates: RFC 5280, updated by RFC 6818
29 * - CSRs: PKCS#10 v1.7 aka RFC 2986
30 * - attributes: PKCS#9 v2.0 aka RFC 2985
31 */
32
Paul Bakkerbdb912d2012-02-13 23:11:30 +000033#include "polarssl/config.h"
34
35#if defined(POLARSSL_X509_WRITE_C)
36
37#include "polarssl/asn1write.h"
38#include "polarssl/x509write.h"
39#include "polarssl/x509.h"
Paul Bakkerc70b9822013-04-07 22:00:46 +020040#include "polarssl/md.h"
41#include "polarssl/oid.h"
Paul Bakkerbdb912d2012-02-13 23:11:30 +000042
Paul Bakker15162a02013-09-06 19:27:21 +020043#include "polarssl/sha1.h"
44
Paul Bakker135f1e92013-08-26 16:54:13 +020045#if defined(POLARSSL_BASE64_C)
46#include "polarssl/base64.h"
47#endif
48
Paul Bakker8eabfc12013-08-25 10:18:25 +020049#if defined(POLARSSL_MEMORY_C)
50#include "polarssl/memory.h"
51#else
52#include <stdlib.h>
53#define polarssl_malloc malloc
54#define polarssl_free free
55#endif
56
Paul Bakker5f45e622013-09-09 12:02:36 +020057static int x509write_string_to_names( asn1_named_data **head, char *name )
Paul Bakker8eabfc12013-08-25 10:18:25 +020058{
59 int ret = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +020060 char *s = name, *c = s;
Paul Bakker8eabfc12013-08-25 10:18:25 +020061 char *end = s + strlen( s );
62 char *oid = NULL;
63 int in_tag = 1;
Paul Bakker5f45e622013-09-09 12:02:36 +020064 asn1_named_data *cur;
Paul Bakker8eabfc12013-08-25 10:18:25 +020065
Manuel Pégourié-Gonnardda7317e2013-09-10 15:52:52 +020066 /* Clear existing chain if present */
67 asn1_free_named_data_list( head );
Paul Bakker8eabfc12013-08-25 10:18:25 +020068
69 while( c <= end )
70 {
71 if( in_tag && *c == '=' )
72 {
73 if( memcmp( s, "CN", 2 ) == 0 && c - s == 2 )
74 oid = OID_AT_CN;
75 else if( memcmp( s, "C", 1 ) == 0 && c - s == 1 )
76 oid = OID_AT_COUNTRY;
77 else if( memcmp( s, "O", 1 ) == 0 && c - s == 1 )
78 oid = OID_AT_ORGANIZATION;
79 else if( memcmp( s, "L", 1 ) == 0 && c - s == 1 )
80 oid = OID_AT_LOCALITY;
81 else if( memcmp( s, "R", 1 ) == 0 && c - s == 1 )
82 oid = OID_PKCS9_EMAIL;
83 else if( memcmp( s, "OU", 2 ) == 0 && c - s == 2 )
84 oid = OID_AT_ORG_UNIT;
85 else if( memcmp( s, "ST", 2 ) == 0 && c - s == 2 )
86 oid = OID_AT_STATE;
87 else
88 {
Paul Bakker0e06c0f2013-08-25 11:21:30 +020089 ret = POLARSSL_ERR_X509WRITE_UNKNOWN_OID;
Paul Bakker8eabfc12013-08-25 10:18:25 +020090 goto exit;
91 }
92
93 s = c + 1;
94 in_tag = 0;
95 }
96
97 if( !in_tag && ( *c == ',' || c == end ) )
98 {
Paul Bakker5f45e622013-09-09 12:02:36 +020099 if( ( cur = asn1_store_named_data( head, oid, strlen( oid ),
100 (unsigned char *) s,
101 c - s ) ) == NULL )
Paul Bakker8eabfc12013-08-25 10:18:25 +0200102 {
Paul Bakker5f45e622013-09-09 12:02:36 +0200103 return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
Paul Bakker8eabfc12013-08-25 10:18:25 +0200104 }
105
Paul Bakkerd4bf8702013-09-09 13:59:11 +0200106 while( c < end && *(c + 1) == ' ' )
107 c++;
108
Paul Bakker8eabfc12013-08-25 10:18:25 +0200109 s = c + 1;
110 in_tag = 1;
111 }
112 c++;
113 }
114
115exit:
116
117 return( ret );
118}
119
Paul Bakker15162a02013-09-06 19:27:21 +0200120/*
121 * RSAPublicKey ::= SEQUENCE {
122 * modulus INTEGER, -- n
123 * publicExponent INTEGER -- e
124 * }
125 */
126static int x509_write_rsa_pubkey( unsigned char **p, unsigned char *start,
127 rsa_context *rsa )
128{
129 int ret;
130 size_t len = 0;
131
132 ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->E ) );
133 ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->N ) );
134
135 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
136 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
137
138 return( len );
139}
140
Paul Bakkercd358032013-09-09 12:08:11 +0200141void x509write_csr_init( x509write_csr *ctx )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200142{
Paul Bakkercd358032013-09-09 12:08:11 +0200143 memset( ctx, 0, sizeof(x509write_csr) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200144}
145
Paul Bakkercd358032013-09-09 12:08:11 +0200146void x509write_csr_free( x509write_csr *ctx )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200147{
Paul Bakker5f45e622013-09-09 12:02:36 +0200148 asn1_free_named_data_list( &ctx->subject );
149 asn1_free_named_data_list( &ctx->extensions );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200150
Paul Bakkercd358032013-09-09 12:08:11 +0200151 memset( ctx, 0, sizeof(x509write_csr) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200152}
153
Paul Bakkercd358032013-09-09 12:08:11 +0200154void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200155{
156 ctx->md_alg = md_alg;
157}
158
Manuel Pégourié-Gonnardee731792013-09-11 22:48:40 +0200159void x509write_csr_set_key( x509write_csr *ctx, pk_context *key )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200160{
Manuel Pégourié-Gonnardee731792013-09-11 22:48:40 +0200161 ctx->key = key;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200162}
163
Paul Bakkercd358032013-09-09 12:08:11 +0200164int x509write_csr_set_subject_name( x509write_csr *ctx, char *subject_name )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200165{
166 return x509write_string_to_names( &ctx->subject, subject_name );
167}
168
Paul Bakker15162a02013-09-06 19:27:21 +0200169/* The first byte of the value in the asn1_named_data structure is reserved
170 * to store the critical boolean for us
171 */
172static int x509_set_extension( asn1_named_data **head,
173 const char *oid, size_t oid_len,
174 int critical,
175 const unsigned char *val, size_t val_len )
Paul Bakkerfde42702013-08-25 14:47:27 +0200176{
Paul Bakkere5eae762013-08-26 12:05:14 +0200177 asn1_named_data *cur;
Paul Bakkere5eae762013-08-26 12:05:14 +0200178
Paul Bakker59ba59f2013-09-09 11:26:00 +0200179 if( ( cur = asn1_store_named_data( head, oid, oid_len,
180 NULL, val_len + 1 ) ) == NULL )
Paul Bakkere5eae762013-08-26 12:05:14 +0200181 {
Paul Bakker59ba59f2013-09-09 11:26:00 +0200182 return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
Paul Bakker1c0e5502013-08-26 13:41:01 +0200183 }
184
Paul Bakker15162a02013-09-06 19:27:21 +0200185 cur->val.p[0] = critical;
186 memcpy( cur->val.p + 1, val, val_len );
Paul Bakker1c0e5502013-08-26 13:41:01 +0200187
188 return( 0 );
189}
190
Paul Bakkercd358032013-09-09 12:08:11 +0200191int x509write_csr_set_extension( x509write_csr *ctx,
Paul Bakker15162a02013-09-06 19:27:21 +0200192 const char *oid, size_t oid_len,
193 const unsigned char *val, size_t val_len )
194{
195 return x509_set_extension( &ctx->extensions, oid, oid_len,
196 0, val, val_len );
197}
198
Paul Bakkercd358032013-09-09 12:08:11 +0200199int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200200{
201 unsigned char buf[4];
202 unsigned char *c;
203 int ret;
204
205 c = buf + 4;
206
Paul Bakker624d03a2013-08-26 14:12:57 +0200207 if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200208 return( ret );
209
210 ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE,
211 OID_SIZE( OID_KEY_USAGE ),
212 buf, 4 );
213 if( ret != 0 )
214 return( ret );
215
216 return( 0 );
217}
218
Paul Bakkercd358032013-09-09 12:08:11 +0200219int x509write_csr_set_ns_cert_type( x509write_csr *ctx,
220 unsigned char ns_cert_type )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200221{
222 unsigned char buf[4];
223 unsigned char *c;
224 int ret;
225
226 c = buf + 4;
227
228 if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
229 return( ret );
230
231 ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE,
232 OID_SIZE( OID_NS_CERT_TYPE ),
233 buf, 4 );
234 if( ret != 0 )
235 return( ret );
Paul Bakkere5eae762013-08-26 12:05:14 +0200236
237 return( 0 );
Paul Bakkerfde42702013-08-25 14:47:27 +0200238}
239
Paul Bakker9397dcb2013-09-06 09:55:26 +0200240void x509write_crt_init( x509write_cert *ctx )
241{
242 memset( ctx, 0, sizeof(x509write_cert) );
243
244 mpi_init( &ctx->serial );
245 ctx->version = X509_CRT_VERSION_3;
246}
247
248void x509write_crt_free( x509write_cert *ctx )
249{
Paul Bakker9397dcb2013-09-06 09:55:26 +0200250 mpi_free( &ctx->serial );
251
Paul Bakker5f45e622013-09-09 12:02:36 +0200252 asn1_free_named_data_list( &ctx->subject );
253 asn1_free_named_data_list( &ctx->issuer );
254 asn1_free_named_data_list( &ctx->extensions );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200255
Paul Bakkercd358032013-09-09 12:08:11 +0200256 memset( ctx, 0, sizeof(x509write_csr) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200257}
258
259void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg )
260{
261 ctx->md_alg = md_alg;
262}
263
264void x509write_crt_set_subject_key( x509write_cert *ctx, rsa_context *rsa )
265{
266 ctx->subject_key = rsa;
267}
268
269void x509write_crt_set_issuer_key( x509write_cert *ctx, rsa_context *rsa )
270{
271 ctx->issuer_key = rsa;
272}
273
274int x509write_crt_set_subject_name( x509write_cert *ctx, char *subject_name )
275{
276 return x509write_string_to_names( &ctx->subject, subject_name );
277}
278
279int x509write_crt_set_issuer_name( x509write_cert *ctx, char *issuer_name )
280{
281 return x509write_string_to_names( &ctx->issuer, issuer_name );
282}
283
284int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial )
285{
286 int ret;
287
288 if( ( ret = mpi_copy( &ctx->serial, serial ) ) != 0 )
289 return( ret );
290
291 return( 0 );
292}
293
294int x509write_crt_set_validity( x509write_cert *ctx, char *not_before,
295 char *not_after )
296{
297 if( strlen(not_before) != X509_RFC5280_UTC_TIME_LEN - 1 ||
298 strlen(not_after) != X509_RFC5280_UTC_TIME_LEN - 1 )
299 {
300 return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
301 }
302 strncpy( ctx->not_before, not_before, X509_RFC5280_UTC_TIME_LEN );
303 strncpy( ctx->not_after , not_after , X509_RFC5280_UTC_TIME_LEN );
304 ctx->not_before[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
305 ctx->not_after[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
306
307 return( 0 );
308}
309
Paul Bakker15162a02013-09-06 19:27:21 +0200310int x509write_crt_set_extension( x509write_cert *ctx,
311 const char *oid, size_t oid_len,
312 int critical,
313 const unsigned char *val, size_t val_len )
314{
315 return x509_set_extension( &ctx->extensions, oid, oid_len,
316 critical, val, val_len );
317}
318
319int x509write_crt_set_basic_constraints( x509write_cert *ctx,
320 int is_ca, int max_pathlen )
321{
322 int ret;
323 unsigned char buf[9];
324 unsigned char *c = buf + sizeof(buf);
325 size_t len = 0;
326
327 memset( buf, 0, sizeof(buf) );
328
329 if( is_ca && max_pathlen > 127 )
330 return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
331
332 if( is_ca )
333 {
334 if( max_pathlen >= 0 )
335 {
336 ASN1_CHK_ADD( len, asn1_write_int( &c, buf, max_pathlen ) );
337 }
338 ASN1_CHK_ADD( len, asn1_write_bool( &c, buf, 1 ) );
339 }
340
341 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
342 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
343
344 return x509write_crt_set_extension( ctx, OID_BASIC_CONSTRAINTS,
345 OID_SIZE( OID_BASIC_CONSTRAINTS ),
346 0, buf + sizeof(buf) - len, len );
347}
348
349int x509write_crt_set_subject_key_identifier( x509write_cert *ctx )
350{
351 int ret;
352 unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
353 unsigned char *c = buf + sizeof(buf);
354 size_t len = 0;
355
356 memset( buf, 0, sizeof(buf));
357 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, ctx->subject_key ) );
358
359 sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
360 c = buf + sizeof(buf) - 20;
361 len = 20;
362
363 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
364 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_OCTET_STRING ) );
365
366 return x509write_crt_set_extension( ctx, OID_SUBJECT_KEY_IDENTIFIER,
367 OID_SIZE( OID_SUBJECT_KEY_IDENTIFIER ),
368 0, buf + sizeof(buf) - len, len );
369}
370
371int x509write_crt_set_authority_key_identifier( x509write_cert *ctx )
372{
373 int ret;
374 unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
375 unsigned char *c = buf + sizeof(buf);
376 size_t len = 0;
377
378 memset( buf, 0, sizeof(buf));
379 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, ctx->issuer_key ) );
380
381 sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
382 c = buf + sizeof(buf) - 20;
383 len = 20;
384
385 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
386 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONTEXT_SPECIFIC | 0 ) );
387
388 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
389 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
390
391 return x509write_crt_set_extension( ctx, OID_AUTHORITY_KEY_IDENTIFIER,
392 OID_SIZE( OID_AUTHORITY_KEY_IDENTIFIER ),
393 0, buf + sizeof(buf) - len, len );
394}
395
Paul Bakker52be08c2013-09-09 12:37:54 +0200396int x509write_crt_set_key_usage( x509write_cert *ctx, unsigned char key_usage )
397{
398 unsigned char buf[4];
399 unsigned char *c;
400 int ret;
401
402 c = buf + 4;
403
404 if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
405 return( ret );
406
407 ret = x509write_crt_set_extension( ctx, OID_KEY_USAGE,
408 OID_SIZE( OID_KEY_USAGE ),
409 1, buf, 4 );
410 if( ret != 0 )
411 return( ret );
412
413 return( 0 );
414}
415
416int x509write_crt_set_ns_cert_type( x509write_cert *ctx,
417 unsigned char ns_cert_type )
418{
419 unsigned char buf[4];
420 unsigned char *c;
421 int ret;
422
423 c = buf + 4;
424
425 if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
426 return( ret );
427
428 ret = x509write_crt_set_extension( ctx, OID_NS_CERT_TYPE,
429 OID_SIZE( OID_NS_CERT_TYPE ),
430 0, buf, 4 );
431 if( ret != 0 )
432 return( ret );
433
434 return( 0 );
435}
436
Manuel Pégourié-Gonnarde1f821a2013-09-12 00:59:40 +0200437int x509write_pubkey_der( pk_context *key, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000438{
439 int ret;
440 unsigned char *c;
441 size_t len = 0;
Manuel Pégourié-Gonnarde1f821a2013-09-12 00:59:40 +0200442 rsa_context *rsa;
443
444 if( !pk_can_do( key, POLARSSL_PK_RSA ) )
445 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
446
447 rsa = pk_rsa( *key );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000448
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200449 c = buf + size;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000450
Paul Bakker15162a02013-09-06 19:27:21 +0200451 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, rsa ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000452
453 if( c - buf < 1 )
454 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
455
Paul Bakker8eabfc12013-08-25 10:18:25 +0200456 /*
457 * SubjectPublicKeyInfo ::= SEQUENCE {
458 * algorithm AlgorithmIdentifier,
459 * subjectPublicKey BIT STRING }
460 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000461 *--c = 0;
462 len += 1;
463
464 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
465 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) );
466
Paul Bakker5f45e622013-09-09 12:02:36 +0200467 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf,
468 OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000469
470 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
471 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
472
473 return( len );
474}
475
Paul Bakker82e29452013-08-25 11:01:31 +0200476int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000477{
478 int ret;
479 unsigned char *c;
480 size_t len = 0;
481
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200482 c = buf + size;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000483
484 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) );
485 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) );
486 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) );
487 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) );
488 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) );
489 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) );
490 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) );
491 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) );
492 ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) );
493
494 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
495 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
496
497 // TODO: Make NON RSA Specific variant later on
498/* *--c = 0;
499 len += 1;
500
501 len += asn1_write_len( &c, len);
502 len += asn1_write_tag( &c, ASN1_BIT_STRING );
503
504 len += asn1_write_oid( &c, OID_PKCS1_RSA );
505
506 len += asn1_write_int( &c, 0 );
507
508 len += asn1_write_len( &c, len);
509 len += asn1_write_tag( &c, ASN1_CONSTRUCTED | ASN1_SEQUENCE );*/
510
511/* for(i = 0; i < len; ++i)
512 {
513 if (i % 16 == 0 ) printf("\n");
514 printf("%02x ", c[i]);
515 }
516 printf("\n");*/
517
518 return( len );
519}
520
Paul Bakker9397dcb2013-09-06 09:55:26 +0200521/*
522 * RelativeDistinguishedName ::=
523 * SET OF AttributeTypeAndValue
524 *
525 * AttributeTypeAndValue ::= SEQUENCE {
526 * type AttributeType,
527 * value AttributeValue }
528 *
529 * AttributeType ::= OBJECT IDENTIFIER
530 *
531 * AttributeValue ::= ANY DEFINED BY AttributeType
532 */
Paul Bakker5f45e622013-09-09 12:02:36 +0200533static int x509_write_name( unsigned char **p, unsigned char *start,
534 const char *oid, size_t oid_len,
535 const unsigned char *name, size_t name_len )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000536{
537 int ret;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000538 size_t len = 0;
539
Paul Bakker05888152012-02-16 10:26:57 +0000540 // Write PrintableString for all except OID_PKCS9_EMAIL
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000541 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200542 if( OID_SIZE( OID_PKCS9_EMAIL ) == oid_len &&
543 memcmp( oid, OID_PKCS9_EMAIL, oid_len ) == 0 )
Paul Bakker05888152012-02-16 10:26:57 +0000544 {
Paul Bakker5f45e622013-09-09 12:02:36 +0200545 ASN1_CHK_ADD( len, asn1_write_ia5_string( p, start,
546 (const char *) name,
547 name_len ) );
Paul Bakker05888152012-02-16 10:26:57 +0000548 }
549 else
Paul Bakker5f45e622013-09-09 12:02:36 +0200550 {
551 ASN1_CHK_ADD( len, asn1_write_printable_string( p, start,
552 (const char *) name,
553 name_len ) );
554 }
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000555
556 // Write OID
557 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200558 ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000559
Paul Bakker5f45e622013-09-09 12:02:36 +0200560 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000561 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
562
563 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
564 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) );
565
566 return( len );
567}
568
Paul Bakker9397dcb2013-09-06 09:55:26 +0200569static int x509_write_names( unsigned char **p, unsigned char *start,
Paul Bakker5f45e622013-09-09 12:02:36 +0200570 asn1_named_data *first )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200571{
572 int ret;
573 size_t len = 0;
Paul Bakker5f45e622013-09-09 12:02:36 +0200574 asn1_named_data *cur = first;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200575
576 while( cur != NULL )
577 {
Paul Bakker5f45e622013-09-09 12:02:36 +0200578 ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p,
579 cur->oid.len,
580 cur->val.p, cur->val.len ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200581 cur = cur->next;
582 }
583
584 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
585 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
586
587 return( len );
588}
589
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200590static int x509_write_sig( unsigned char **p, unsigned char *start,
Paul Bakker1c3853b2013-09-10 11:43:44 +0200591 const char *oid, size_t oid_len,
592 unsigned char *sig, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000593{
594 int ret;
595 size_t len = 0;
596
597 if( *p - start < (int) size + 1 )
598 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
599
600 len = size;
601 (*p) -= len;
602 memcpy( *p, sig, len );
603
604 *--(*p) = 0;
605 len += 1;
606
607 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
608 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
609
610 // Write OID
611 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200612 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid,
Paul Bakker1c3853b2013-09-10 11:43:44 +0200613 oid_len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000614
615 return( len );
616}
617
Paul Bakker9397dcb2013-09-06 09:55:26 +0200618static int x509_write_time( unsigned char **p, unsigned char *start,
619 const char *time, size_t size )
620{
621 int ret;
622 size_t len = 0;
623
Paul Bakker9c208aa2013-09-08 15:44:31 +0200624 /*
625 * write ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
626 */
627 if( time[0] == '2' && time[1] == '0' && time [2] < '5' )
628 {
629 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
630 (const unsigned char *) time + 2,
631 size - 2 ) );
632 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
633 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_UTC_TIME ) );
634 }
635 else
636 {
637 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
638 (const unsigned char *) time,
639 size ) );
640 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
641 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_GENERALIZED_TIME ) );
642 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200643
644 return( len );
645}
646
Paul Bakker15162a02013-09-06 19:27:21 +0200647static int x509_write_extension( unsigned char **p, unsigned char *start,
648 asn1_named_data *ext )
649{
650 int ret;
651 size_t len = 0;
652
653 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->val.p + 1,
654 ext->val.len - 1 ) );
655 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->val.len - 1 ) );
656 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) );
657
658 if( ext->val.p[0] != 0 )
659 {
660 ASN1_CHK_ADD( len, asn1_write_bool( p, start, 1 ) );
661 }
662
663 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->oid.p,
664 ext->oid.len ) );
665 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->oid.len ) );
666 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) );
667
668 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
669 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
670
671 return( len );
672}
673
674/*
675 * Extension ::= SEQUENCE {
676 * extnID OBJECT IDENTIFIER,
677 * critical BOOLEAN DEFAULT FALSE,
678 * extnValue OCTET STRING
679 * -- contains the DER encoding of an ASN.1 value
680 * -- corresponding to the extension type identified
681 * -- by extnID
682 * }
683 */
684static int x509_write_extensions( unsigned char **p, unsigned char *start,
685 asn1_named_data *first )
686{
687 int ret;
688 size_t len = 0;
689 asn1_named_data *cur_ext = first;
690
691 while( cur_ext != NULL )
692 {
693 ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
694 cur_ext = cur_ext->next;
695 }
696
697 return( len );
698}
699
Manuel Pégourié-Gonnardee731792013-09-11 22:48:40 +0200700int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size,
701 int (*f_rng)(void *, unsigned char *, size_t),
702 void *p_rng )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000703{
704 int ret;
Paul Bakkerc70b9822013-04-07 22:00:46 +0200705 const char *sig_oid;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200706 size_t sig_oid_len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000707 unsigned char *c, *c2;
Paul Bakker3cac5e02012-02-16 14:08:06 +0000708 unsigned char hash[64];
709 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000710 unsigned char tmp_buf[2048];
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200711 size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000712 size_t len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000713
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200714 /*
715 * Prepare data to be signed in tmp_buf
716 */
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200717 c = tmp_buf + sizeof( tmp_buf );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000718
Paul Bakker15162a02013-09-06 19:27:21 +0200719 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200720
Paul Bakkere5eae762013-08-26 12:05:14 +0200721 if( len )
Paul Bakkerfde42702013-08-25 14:47:27 +0200722 {
Paul Bakkere5eae762013-08-26 12:05:14 +0200723 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
724 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200725
Paul Bakkere5eae762013-08-26 12:05:14 +0200726 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
727 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200728
Paul Bakker5f45e622013-09-09 12:02:36 +0200729 ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ,
730 OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200731
Paul Bakkere5eae762013-08-26 12:05:14 +0200732 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
733 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200734 }
735
Paul Bakkere5eae762013-08-26 12:05:14 +0200736 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000737 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) );
738
Manuel Pégourié-Gonnarde1f821a2013-09-12 00:59:40 +0200739 ASN1_CHK_ADD( pub_len, x509write_pubkey_der( ctx->key,
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200740 tmp_buf, c - tmp_buf ) );
Manuel Pégourié-Gonnard6dcf0bf2013-09-11 13:09:04 +0200741 c -= pub_len;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000742 len += pub_len;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000743
Paul Bakker9397dcb2013-09-06 09:55:26 +0200744 /*
745 * Subject ::= Name
746 */
747 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000748
Paul Bakker8eabfc12013-08-25 10:18:25 +0200749 /*
750 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
751 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000752 ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
753
754 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
755 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200756
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200757 /*
758 * Prepare signature
759 */
Paul Bakker8eabfc12013-08-25 10:18:25 +0200760 md( md_info_from_type( ctx->md_alg ), c, len, hash );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000761
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200762 if( ( ret = pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,
Manuel Pégourié-Gonnardee731792013-09-11 22:48:40 +0200763 f_rng, p_rng ) ) != 0 ||
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200764 ( ret = oid_get_oid_by_sig_alg( pk_get_type( ctx->key ), ctx->md_alg,
765 &sig_oid, &sig_oid_len ) ) != 0 )
766 {
767 return( ret );
768 }
Manuel Pégourié-Gonnard5353a032013-09-11 12:14:26 +0200769
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200770 /*
771 * Write data to output buffer
772 */
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200773 c2 = buf + size;
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200774 ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf,
775 sig_oid, sig_oid_len, sig, sig_len ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200776
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000777 c2 -= len;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200778 memcpy( c2, c, len );
779
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200780 len += sig_and_oid_len;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000781 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
782 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
783
784 return( len );
785}
786
Paul Bakker9397dcb2013-09-06 09:55:26 +0200787int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size )
788{
789 int ret;
790 const char *sig_oid;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200791 size_t sig_oid_len = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200792 unsigned char *c, *c2;
793 unsigned char hash[64];
794 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
795 unsigned char tmp_buf[2048];
796 size_t sub_len = 0, pub_len = 0, sig_len = 0;
797 size_t len = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200798
Manuel Pégourié-Gonnarde1f821a2013-09-12 00:59:40 +0200799 // temporary compatibility hack
800 pk_context subject_key;
801 subject_key.pk_info = pk_info_from_type( POLARSSL_PK_RSA );
802 subject_key.pk_ctx = ctx->subject_key;
803
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200804 c = tmp_buf + sizeof( tmp_buf );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200805
806 // Generate correct OID
807 //
Paul Bakker1c3853b2013-09-10 11:43:44 +0200808 ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid,
809 &sig_oid_len );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200810 if( ret != 0 )
811 return( ret );
812
Paul Bakker15162a02013-09-06 19:27:21 +0200813 /*
814 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
815 */
816 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
817 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
818 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
819 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
820 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200821
822 /*
Manuel Pégourié-Gonnard6dcf0bf2013-09-11 13:09:04 +0200823 * SubjectPublicKeyInfo
Paul Bakker9397dcb2013-09-06 09:55:26 +0200824 */
Manuel Pégourié-Gonnarde1f821a2013-09-12 00:59:40 +0200825 ASN1_CHK_ADD( pub_len, x509write_pubkey_der( &subject_key,
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200826 tmp_buf, c - tmp_buf ) );
Manuel Pégourié-Gonnard6dcf0bf2013-09-11 13:09:04 +0200827 c -= pub_len;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200828 len += pub_len;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200829
830 /*
831 * Subject ::= Name
832 */
833 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
834
835 /*
836 * Validity ::= SEQUENCE {
837 * notBefore Time,
838 * notAfter Time }
839 */
840 sub_len = 0;
841
842 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
843 X509_RFC5280_UTC_TIME_LEN ) );
844
845 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
846 X509_RFC5280_UTC_TIME_LEN ) );
847
848 len += sub_len;
849 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
850 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
851
852 /*
853 * Issuer ::= Name
854 */
855 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->issuer ) );
856
857 /*
858 * Signature ::= AlgorithmIdentifier
859 */
860 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf,
Paul Bakker5f45e622013-09-09 12:02:36 +0200861 sig_oid, strlen( sig_oid ) ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200862
863 /*
864 * Serial ::= INTEGER
865 */
866 ASN1_CHK_ADD( len, asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
867
868 /*
869 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
870 */
871 sub_len = 0;
872 ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) );
873 len += sub_len;
874 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
875 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) );
876
877 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
878 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
879
880 md( md_info_from_type( ctx->md_alg ), c, len, hash );
881
882 rsa_pkcs1_sign( ctx->issuer_key, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig );
883
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200884 c2 = buf + size;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200885 ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len,
886 sig, ctx->issuer_key->len ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200887
888 c2 -= len;
889 memcpy( c2, c, len );
890
891 len += sig_len;
892 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
893 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
894
895 return( len );
896}
897
898#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
899#define PEM_END_CRT "-----END CERTIFICATE-----\n"
900
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200901#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n"
902#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n"
903
904#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n"
905#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n"
906
907#define PEM_BEGIN_PRIVATE_KEY "-----BEGIN RSA PRIVATE KEY-----\n"
908#define PEM_END_PRIVATE_KEY "-----END RSA PRIVATE KEY-----\n"
Paul Bakker135f1e92013-08-26 16:54:13 +0200909
910#if defined(POLARSSL_BASE64_C)
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200911static int x509write_pemify( const char *begin_str, const char *end_str,
912 const unsigned char *der_data, size_t der_len,
913 unsigned char *buf, size_t size )
Paul Bakker135f1e92013-08-26 16:54:13 +0200914{
915 int ret;
Paul Bakker135f1e92013-08-26 16:54:13 +0200916 unsigned char base_buf[4096];
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200917 unsigned char *c = base_buf, *p = buf;
918 size_t len = 0, olen = sizeof(base_buf);
Paul Bakker135f1e92013-08-26 16:54:13 +0200919
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200920 if( ( ret = base64_encode( base_buf, &olen, der_data, der_len ) ) != 0 )
Paul Bakker135f1e92013-08-26 16:54:13 +0200921 return( ret );
922
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200923 if( olen + strlen( begin_str ) + strlen( end_str ) +
Paul Bakker135f1e92013-08-26 16:54:13 +0200924 olen / 64 > size )
925 {
926 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
927 }
928
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200929 memcpy( p, begin_str, strlen( begin_str ) );
930 p += strlen( begin_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200931
932 while( olen )
933 {
934 len = ( olen > 64 ) ? 64 : olen;
935 memcpy( p, c, len );
936 olen -= len;
937 p += len;
938 c += len;
939 *p++ = '\n';
940 }
941
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200942 memcpy( p, end_str, strlen( end_str ) );
943 p += strlen( end_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200944
945 *p = '\0';
946
947 return( 0 );
948}
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200949
Paul Bakker9397dcb2013-09-06 09:55:26 +0200950int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size )
951{
952 int ret;
953 unsigned char output_buf[4096];
954
955 if( ( ret = x509write_crt_der( crt, output_buf,
956 sizeof(output_buf) ) ) < 0 )
957 {
958 return( ret );
959 }
960
961 if( ( ret = x509write_pemify( PEM_BEGIN_CRT, PEM_END_CRT,
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200962 output_buf + sizeof(output_buf) - ret,
Paul Bakker9397dcb2013-09-06 09:55:26 +0200963 ret, buf, size ) ) != 0 )
964 {
965 return( ret );
966 }
967
968 return( 0 );
969}
970
Manuel Pégourié-Gonnarde1f821a2013-09-12 00:59:40 +0200971int x509write_pubkey_pem( pk_context *key, unsigned char *buf, size_t size )
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200972{
973 int ret;
974 unsigned char output_buf[4096];
975
Manuel Pégourié-Gonnarde1f821a2013-09-12 00:59:40 +0200976 if( ( ret = x509write_pubkey_der( key, output_buf,
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200977 sizeof(output_buf) ) ) < 0 )
978 {
979 return( ret );
980 }
981
982 if( ( ret = x509write_pemify( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200983 output_buf + sizeof(output_buf) - ret,
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200984 ret, buf, size ) ) != 0 )
985 {
986 return( ret );
987 }
988
989 return( 0 );
990}
991
992int x509write_key_pem( rsa_context *rsa, unsigned char *buf, size_t size )
993{
994 int ret;
995 unsigned char output_buf[4096];
996
997 if( ( ret = x509write_key_der( rsa, output_buf,
998 sizeof(output_buf) ) ) < 0 )
999 {
1000 return( ret );
1001 }
1002
1003 if( ( ret = x509write_pemify( PEM_BEGIN_PRIVATE_KEY, PEM_END_PRIVATE_KEY,
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +02001004 output_buf + sizeof(output_buf) - ret,
Paul Bakkerf3df61a2013-08-26 17:22:23 +02001005 ret, buf, size ) ) != 0 )
1006 {
1007 return( ret );
1008 }
1009
1010 return( 0 );
1011}
1012
Manuel Pégourié-Gonnardee731792013-09-11 22:48:40 +02001013int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size,
1014 int (*f_rng)(void *, unsigned char *, size_t),
1015 void *p_rng )
Paul Bakkerf3df61a2013-08-26 17:22:23 +02001016{
1017 int ret;
1018 unsigned char output_buf[4096];
1019
Manuel Pégourié-Gonnardee731792013-09-11 22:48:40 +02001020 if( ( ret = x509write_csr_der( ctx, output_buf, sizeof(output_buf),
1021 f_rng, p_rng ) ) < 0 )
Paul Bakkerf3df61a2013-08-26 17:22:23 +02001022 {
1023 return( ret );
1024 }
1025
1026 if( ( ret = x509write_pemify( PEM_BEGIN_CSR, PEM_END_CSR,
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +02001027 output_buf + sizeof(output_buf) - ret,
Paul Bakkerf3df61a2013-08-26 17:22:23 +02001028 ret, buf, size ) ) != 0 )
1029 {
1030 return( ret );
1031 }
1032
1033 return( 0 );
1034}
Paul Bakker135f1e92013-08-26 16:54:13 +02001035#endif /* POLARSSL_BASE64_C */
1036
Paul Bakkerbdb912d2012-02-13 23:11:30 +00001037#endif