blob: 39a37ba1793c2c964fae1746f93a5e8dd3e449b7 [file] [log] [blame]
Paul Bakkerbdb912d2012-02-13 23:11:30 +00001/*
2 * X509 buffer writing functionality
3 *
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +02004 * Copyright (C) 2006-2013, Brainspark B.V.
Paul Bakkerbdb912d2012-02-13 23:11:30 +00005 *
6 * This file is part of PolarSSL (http://www.polarssl.org)
7 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
8 *
9 * All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 */
25
26#include "polarssl/config.h"
27
28#if defined(POLARSSL_X509_WRITE_C)
29
30#include "polarssl/asn1write.h"
31#include "polarssl/x509write.h"
32#include "polarssl/x509.h"
Paul Bakkerc70b9822013-04-07 22:00:46 +020033#include "polarssl/md.h"
34#include "polarssl/oid.h"
Paul Bakkerbdb912d2012-02-13 23:11:30 +000035
Paul Bakker15162a02013-09-06 19:27:21 +020036#include "polarssl/sha1.h"
37
Paul Bakker135f1e92013-08-26 16:54:13 +020038#if defined(POLARSSL_BASE64_C)
39#include "polarssl/base64.h"
40#endif
41
Paul Bakker8eabfc12013-08-25 10:18:25 +020042#if defined(POLARSSL_MEMORY_C)
43#include "polarssl/memory.h"
44#else
45#include <stdlib.h>
46#define polarssl_malloc malloc
47#define polarssl_free free
48#endif
49
Paul Bakker5f45e622013-09-09 12:02:36 +020050static int x509write_string_to_names( asn1_named_data **head, char *name )
Paul Bakker8eabfc12013-08-25 10:18:25 +020051{
52 int ret = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +020053 char *s = name, *c = s;
Paul Bakker8eabfc12013-08-25 10:18:25 +020054 char *end = s + strlen( s );
55 char *oid = NULL;
56 int in_tag = 1;
Paul Bakker5f45e622013-09-09 12:02:36 +020057 asn1_named_data *cur;
Paul Bakker8eabfc12013-08-25 10:18:25 +020058
Manuel Pégourié-Gonnardda7317e2013-09-10 15:52:52 +020059 /* Clear existing chain if present */
60 asn1_free_named_data_list( head );
Paul Bakker8eabfc12013-08-25 10:18:25 +020061
62 while( c <= end )
63 {
64 if( in_tag && *c == '=' )
65 {
66 if( memcmp( s, "CN", 2 ) == 0 && c - s == 2 )
67 oid = OID_AT_CN;
68 else if( memcmp( s, "C", 1 ) == 0 && c - s == 1 )
69 oid = OID_AT_COUNTRY;
70 else if( memcmp( s, "O", 1 ) == 0 && c - s == 1 )
71 oid = OID_AT_ORGANIZATION;
72 else if( memcmp( s, "L", 1 ) == 0 && c - s == 1 )
73 oid = OID_AT_LOCALITY;
74 else if( memcmp( s, "R", 1 ) == 0 && c - s == 1 )
75 oid = OID_PKCS9_EMAIL;
76 else if( memcmp( s, "OU", 2 ) == 0 && c - s == 2 )
77 oid = OID_AT_ORG_UNIT;
78 else if( memcmp( s, "ST", 2 ) == 0 && c - s == 2 )
79 oid = OID_AT_STATE;
80 else
81 {
Paul Bakker0e06c0f2013-08-25 11:21:30 +020082 ret = POLARSSL_ERR_X509WRITE_UNKNOWN_OID;
Paul Bakker8eabfc12013-08-25 10:18:25 +020083 goto exit;
84 }
85
86 s = c + 1;
87 in_tag = 0;
88 }
89
90 if( !in_tag && ( *c == ',' || c == end ) )
91 {
Paul Bakker5f45e622013-09-09 12:02:36 +020092 if( ( cur = asn1_store_named_data( head, oid, strlen( oid ),
93 (unsigned char *) s,
94 c - s ) ) == NULL )
Paul Bakker8eabfc12013-08-25 10:18:25 +020095 {
Paul Bakker5f45e622013-09-09 12:02:36 +020096 return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
Paul Bakker8eabfc12013-08-25 10:18:25 +020097 }
98
Paul Bakkerd4bf8702013-09-09 13:59:11 +020099 while( c < end && *(c + 1) == ' ' )
100 c++;
101
Paul Bakker8eabfc12013-08-25 10:18:25 +0200102 s = c + 1;
103 in_tag = 1;
104 }
105 c++;
106 }
107
108exit:
109
110 return( ret );
111}
112
Paul Bakker15162a02013-09-06 19:27:21 +0200113/*
114 * RSAPublicKey ::= SEQUENCE {
115 * modulus INTEGER, -- n
116 * publicExponent INTEGER -- e
117 * }
118 */
119static int x509_write_rsa_pubkey( unsigned char **p, unsigned char *start,
120 rsa_context *rsa )
121{
122 int ret;
123 size_t len = 0;
124
125 ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->E ) );
126 ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->N ) );
127
128 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
129 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
130
131 return( len );
132}
133
Paul Bakkercd358032013-09-09 12:08:11 +0200134void x509write_csr_init( x509write_csr *ctx )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200135{
Paul Bakkercd358032013-09-09 12:08:11 +0200136 memset( ctx, 0, sizeof(x509write_csr) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200137}
138
Paul Bakkercd358032013-09-09 12:08:11 +0200139void x509write_csr_free( x509write_csr *ctx )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200140{
Paul Bakker5f45e622013-09-09 12:02:36 +0200141 asn1_free_named_data_list( &ctx->subject );
142 asn1_free_named_data_list( &ctx->extensions );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200143
Paul Bakkercd358032013-09-09 12:08:11 +0200144 memset( ctx, 0, sizeof(x509write_csr) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200145}
146
Paul Bakkercd358032013-09-09 12:08:11 +0200147void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200148{
149 ctx->md_alg = md_alg;
150}
151
Manuel Pégourié-Gonnard5353a032013-09-11 12:14:26 +0200152// TODO: take a pk_context
153// TODO: return int
Paul Bakkercd358032013-09-09 12:08:11 +0200154void x509write_csr_set_rsa_key( x509write_csr *ctx, rsa_context *rsa )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200155{
Manuel Pégourié-Gonnard5353a032013-09-11 12:14:26 +0200156 // temporary
157 ctx->key = polarssl_malloc( sizeof( pk_context ) );
158
159 // TODO: check errors
160 pk_init_ctx( ctx->key, pk_info_from_type( POLARSSL_PK_RSA ) );
161 rsa_copy( pk_rsa( *ctx->key ), rsa );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200162}
163
Paul Bakkercd358032013-09-09 12:08:11 +0200164int x509write_csr_set_subject_name( x509write_csr *ctx, char *subject_name )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200165{
166 return x509write_string_to_names( &ctx->subject, subject_name );
167}
168
Paul Bakker15162a02013-09-06 19:27:21 +0200169/* The first byte of the value in the asn1_named_data structure is reserved
170 * to store the critical boolean for us
171 */
172static int x509_set_extension( asn1_named_data **head,
173 const char *oid, size_t oid_len,
174 int critical,
175 const unsigned char *val, size_t val_len )
Paul Bakkerfde42702013-08-25 14:47:27 +0200176{
Paul Bakkere5eae762013-08-26 12:05:14 +0200177 asn1_named_data *cur;
Paul Bakkere5eae762013-08-26 12:05:14 +0200178
Paul Bakker59ba59f2013-09-09 11:26:00 +0200179 if( ( cur = asn1_store_named_data( head, oid, oid_len,
180 NULL, val_len + 1 ) ) == NULL )
Paul Bakkere5eae762013-08-26 12:05:14 +0200181 {
Paul Bakker59ba59f2013-09-09 11:26:00 +0200182 return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
Paul Bakker1c0e5502013-08-26 13:41:01 +0200183 }
184
Paul Bakker15162a02013-09-06 19:27:21 +0200185 cur->val.p[0] = critical;
186 memcpy( cur->val.p + 1, val, val_len );
Paul Bakker1c0e5502013-08-26 13:41:01 +0200187
188 return( 0 );
189}
190
Paul Bakkercd358032013-09-09 12:08:11 +0200191int x509write_csr_set_extension( x509write_csr *ctx,
Paul Bakker15162a02013-09-06 19:27:21 +0200192 const char *oid, size_t oid_len,
193 const unsigned char *val, size_t val_len )
194{
195 return x509_set_extension( &ctx->extensions, oid, oid_len,
196 0, val, val_len );
197}
198
Paul Bakkercd358032013-09-09 12:08:11 +0200199int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200200{
201 unsigned char buf[4];
202 unsigned char *c;
203 int ret;
204
205 c = buf + 4;
206
Paul Bakker624d03a2013-08-26 14:12:57 +0200207 if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200208 return( ret );
209
210 ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE,
211 OID_SIZE( OID_KEY_USAGE ),
212 buf, 4 );
213 if( ret != 0 )
214 return( ret );
215
216 return( 0 );
217}
218
Paul Bakkercd358032013-09-09 12:08:11 +0200219int x509write_csr_set_ns_cert_type( x509write_csr *ctx,
220 unsigned char ns_cert_type )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200221{
222 unsigned char buf[4];
223 unsigned char *c;
224 int ret;
225
226 c = buf + 4;
227
228 if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
229 return( ret );
230
231 ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE,
232 OID_SIZE( OID_NS_CERT_TYPE ),
233 buf, 4 );
234 if( ret != 0 )
235 return( ret );
Paul Bakkere5eae762013-08-26 12:05:14 +0200236
237 return( 0 );
Paul Bakkerfde42702013-08-25 14:47:27 +0200238}
239
Paul Bakker9397dcb2013-09-06 09:55:26 +0200240void x509write_crt_init( x509write_cert *ctx )
241{
242 memset( ctx, 0, sizeof(x509write_cert) );
243
244 mpi_init( &ctx->serial );
245 ctx->version = X509_CRT_VERSION_3;
246}
247
248void x509write_crt_free( x509write_cert *ctx )
249{
Paul Bakker9397dcb2013-09-06 09:55:26 +0200250 mpi_free( &ctx->serial );
251
Paul Bakker5f45e622013-09-09 12:02:36 +0200252 asn1_free_named_data_list( &ctx->subject );
253 asn1_free_named_data_list( &ctx->issuer );
254 asn1_free_named_data_list( &ctx->extensions );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200255
Paul Bakkercd358032013-09-09 12:08:11 +0200256 memset( ctx, 0, sizeof(x509write_csr) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200257}
258
259void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg )
260{
261 ctx->md_alg = md_alg;
262}
263
264void x509write_crt_set_subject_key( x509write_cert *ctx, rsa_context *rsa )
265{
266 ctx->subject_key = rsa;
267}
268
269void x509write_crt_set_issuer_key( x509write_cert *ctx, rsa_context *rsa )
270{
271 ctx->issuer_key = rsa;
272}
273
274int x509write_crt_set_subject_name( x509write_cert *ctx, char *subject_name )
275{
276 return x509write_string_to_names( &ctx->subject, subject_name );
277}
278
279int x509write_crt_set_issuer_name( x509write_cert *ctx, char *issuer_name )
280{
281 return x509write_string_to_names( &ctx->issuer, issuer_name );
282}
283
284int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial )
285{
286 int ret;
287
288 if( ( ret = mpi_copy( &ctx->serial, serial ) ) != 0 )
289 return( ret );
290
291 return( 0 );
292}
293
294int x509write_crt_set_validity( x509write_cert *ctx, char *not_before,
295 char *not_after )
296{
297 if( strlen(not_before) != X509_RFC5280_UTC_TIME_LEN - 1 ||
298 strlen(not_after) != X509_RFC5280_UTC_TIME_LEN - 1 )
299 {
300 return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
301 }
302 strncpy( ctx->not_before, not_before, X509_RFC5280_UTC_TIME_LEN );
303 strncpy( ctx->not_after , not_after , X509_RFC5280_UTC_TIME_LEN );
304 ctx->not_before[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
305 ctx->not_after[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
306
307 return( 0 );
308}
309
Paul Bakker15162a02013-09-06 19:27:21 +0200310int x509write_crt_set_extension( x509write_cert *ctx,
311 const char *oid, size_t oid_len,
312 int critical,
313 const unsigned char *val, size_t val_len )
314{
315 return x509_set_extension( &ctx->extensions, oid, oid_len,
316 critical, val, val_len );
317}
318
319int x509write_crt_set_basic_constraints( x509write_cert *ctx,
320 int is_ca, int max_pathlen )
321{
322 int ret;
323 unsigned char buf[9];
324 unsigned char *c = buf + sizeof(buf);
325 size_t len = 0;
326
327 memset( buf, 0, sizeof(buf) );
328
329 if( is_ca && max_pathlen > 127 )
330 return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
331
332 if( is_ca )
333 {
334 if( max_pathlen >= 0 )
335 {
336 ASN1_CHK_ADD( len, asn1_write_int( &c, buf, max_pathlen ) );
337 }
338 ASN1_CHK_ADD( len, asn1_write_bool( &c, buf, 1 ) );
339 }
340
341 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
342 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
343
344 return x509write_crt_set_extension( ctx, OID_BASIC_CONSTRAINTS,
345 OID_SIZE( OID_BASIC_CONSTRAINTS ),
346 0, buf + sizeof(buf) - len, len );
347}
348
349int x509write_crt_set_subject_key_identifier( x509write_cert *ctx )
350{
351 int ret;
352 unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
353 unsigned char *c = buf + sizeof(buf);
354 size_t len = 0;
355
356 memset( buf, 0, sizeof(buf));
357 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, ctx->subject_key ) );
358
359 sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
360 c = buf + sizeof(buf) - 20;
361 len = 20;
362
363 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
364 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_OCTET_STRING ) );
365
366 return x509write_crt_set_extension( ctx, OID_SUBJECT_KEY_IDENTIFIER,
367 OID_SIZE( OID_SUBJECT_KEY_IDENTIFIER ),
368 0, buf + sizeof(buf) - len, len );
369}
370
371int x509write_crt_set_authority_key_identifier( x509write_cert *ctx )
372{
373 int ret;
374 unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
375 unsigned char *c = buf + sizeof(buf);
376 size_t len = 0;
377
378 memset( buf, 0, sizeof(buf));
379 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, ctx->issuer_key ) );
380
381 sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
382 c = buf + sizeof(buf) - 20;
383 len = 20;
384
385 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
386 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONTEXT_SPECIFIC | 0 ) );
387
388 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
389 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
390
391 return x509write_crt_set_extension( ctx, OID_AUTHORITY_KEY_IDENTIFIER,
392 OID_SIZE( OID_AUTHORITY_KEY_IDENTIFIER ),
393 0, buf + sizeof(buf) - len, len );
394}
395
Paul Bakker52be08c2013-09-09 12:37:54 +0200396int x509write_crt_set_key_usage( x509write_cert *ctx, unsigned char key_usage )
397{
398 unsigned char buf[4];
399 unsigned char *c;
400 int ret;
401
402 c = buf + 4;
403
404 if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
405 return( ret );
406
407 ret = x509write_crt_set_extension( ctx, OID_KEY_USAGE,
408 OID_SIZE( OID_KEY_USAGE ),
409 1, buf, 4 );
410 if( ret != 0 )
411 return( ret );
412
413 return( 0 );
414}
415
416int x509write_crt_set_ns_cert_type( x509write_cert *ctx,
417 unsigned char ns_cert_type )
418{
419 unsigned char buf[4];
420 unsigned char *c;
421 int ret;
422
423 c = buf + 4;
424
425 if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
426 return( ret );
427
428 ret = x509write_crt_set_extension( ctx, OID_NS_CERT_TYPE,
429 OID_SIZE( OID_NS_CERT_TYPE ),
430 0, buf, 4 );
431 if( ret != 0 )
432 return( ret );
433
434 return( 0 );
435}
436
Paul Bakker82e29452013-08-25 11:01:31 +0200437int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000438{
439 int ret;
440 unsigned char *c;
441 size_t len = 0;
442
443 c = buf + size - 1;
444
Paul Bakker15162a02013-09-06 19:27:21 +0200445 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, rsa ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000446
447 if( c - buf < 1 )
448 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
449
Paul Bakker8eabfc12013-08-25 10:18:25 +0200450 /*
451 * SubjectPublicKeyInfo ::= SEQUENCE {
452 * algorithm AlgorithmIdentifier,
453 * subjectPublicKey BIT STRING }
454 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000455 *--c = 0;
456 len += 1;
457
458 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
459 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) );
460
Paul Bakker5f45e622013-09-09 12:02:36 +0200461 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf,
462 OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000463
464 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
465 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
466
467 return( len );
468}
469
Paul Bakker82e29452013-08-25 11:01:31 +0200470int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000471{
472 int ret;
473 unsigned char *c;
474 size_t len = 0;
475
476 c = buf + size - 1;
477
478 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) );
479 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) );
480 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) );
481 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) );
482 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) );
483 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) );
484 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) );
485 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) );
486 ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) );
487
488 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
489 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
490
491 // TODO: Make NON RSA Specific variant later on
492/* *--c = 0;
493 len += 1;
494
495 len += asn1_write_len( &c, len);
496 len += asn1_write_tag( &c, ASN1_BIT_STRING );
497
498 len += asn1_write_oid( &c, OID_PKCS1_RSA );
499
500 len += asn1_write_int( &c, 0 );
501
502 len += asn1_write_len( &c, len);
503 len += asn1_write_tag( &c, ASN1_CONSTRUCTED | ASN1_SEQUENCE );*/
504
505/* for(i = 0; i < len; ++i)
506 {
507 if (i % 16 == 0 ) printf("\n");
508 printf("%02x ", c[i]);
509 }
510 printf("\n");*/
511
512 return( len );
513}
514
Paul Bakker9397dcb2013-09-06 09:55:26 +0200515/*
516 * RelativeDistinguishedName ::=
517 * SET OF AttributeTypeAndValue
518 *
519 * AttributeTypeAndValue ::= SEQUENCE {
520 * type AttributeType,
521 * value AttributeValue }
522 *
523 * AttributeType ::= OBJECT IDENTIFIER
524 *
525 * AttributeValue ::= ANY DEFINED BY AttributeType
526 */
Paul Bakker5f45e622013-09-09 12:02:36 +0200527static int x509_write_name( unsigned char **p, unsigned char *start,
528 const char *oid, size_t oid_len,
529 const unsigned char *name, size_t name_len )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000530{
531 int ret;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000532 size_t len = 0;
533
Paul Bakker05888152012-02-16 10:26:57 +0000534 // Write PrintableString for all except OID_PKCS9_EMAIL
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000535 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200536 if( OID_SIZE( OID_PKCS9_EMAIL ) == oid_len &&
537 memcmp( oid, OID_PKCS9_EMAIL, oid_len ) == 0 )
Paul Bakker05888152012-02-16 10:26:57 +0000538 {
Paul Bakker5f45e622013-09-09 12:02:36 +0200539 ASN1_CHK_ADD( len, asn1_write_ia5_string( p, start,
540 (const char *) name,
541 name_len ) );
Paul Bakker05888152012-02-16 10:26:57 +0000542 }
543 else
Paul Bakker5f45e622013-09-09 12:02:36 +0200544 {
545 ASN1_CHK_ADD( len, asn1_write_printable_string( p, start,
546 (const char *) name,
547 name_len ) );
548 }
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000549
550 // Write OID
551 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200552 ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000553
Paul Bakker5f45e622013-09-09 12:02:36 +0200554 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000555 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
556
557 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
558 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) );
559
560 return( len );
561}
562
Paul Bakker9397dcb2013-09-06 09:55:26 +0200563static int x509_write_names( unsigned char **p, unsigned char *start,
Paul Bakker5f45e622013-09-09 12:02:36 +0200564 asn1_named_data *first )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200565{
566 int ret;
567 size_t len = 0;
Paul Bakker5f45e622013-09-09 12:02:36 +0200568 asn1_named_data *cur = first;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200569
570 while( cur != NULL )
571 {
Paul Bakker5f45e622013-09-09 12:02:36 +0200572 ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p,
573 cur->oid.len,
574 cur->val.p, cur->val.len ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200575 cur = cur->next;
576 }
577
578 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
579 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
580
581 return( len );
582}
583
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200584static int x509_write_sig( unsigned char **p, unsigned char *start,
Paul Bakker1c3853b2013-09-10 11:43:44 +0200585 const char *oid, size_t oid_len,
586 unsigned char *sig, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000587{
588 int ret;
589 size_t len = 0;
590
591 if( *p - start < (int) size + 1 )
592 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
593
594 len = size;
595 (*p) -= len;
596 memcpy( *p, sig, len );
597
598 *--(*p) = 0;
599 len += 1;
600
601 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
602 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
603
604 // Write OID
605 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200606 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid,
Paul Bakker1c3853b2013-09-10 11:43:44 +0200607 oid_len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000608
609 return( len );
610}
611
Paul Bakker9397dcb2013-09-06 09:55:26 +0200612static int x509_write_time( unsigned char **p, unsigned char *start,
613 const char *time, size_t size )
614{
615 int ret;
616 size_t len = 0;
617
Paul Bakker9c208aa2013-09-08 15:44:31 +0200618 /*
619 * write ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
620 */
621 if( time[0] == '2' && time[1] == '0' && time [2] < '5' )
622 {
623 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
624 (const unsigned char *) time + 2,
625 size - 2 ) );
626 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
627 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_UTC_TIME ) );
628 }
629 else
630 {
631 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
632 (const unsigned char *) time,
633 size ) );
634 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
635 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_GENERALIZED_TIME ) );
636 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200637
638 return( len );
639}
640
Paul Bakker15162a02013-09-06 19:27:21 +0200641static int x509_write_extension( unsigned char **p, unsigned char *start,
642 asn1_named_data *ext )
643{
644 int ret;
645 size_t len = 0;
646
647 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->val.p + 1,
648 ext->val.len - 1 ) );
649 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->val.len - 1 ) );
650 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) );
651
652 if( ext->val.p[0] != 0 )
653 {
654 ASN1_CHK_ADD( len, asn1_write_bool( p, start, 1 ) );
655 }
656
657 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->oid.p,
658 ext->oid.len ) );
659 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->oid.len ) );
660 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) );
661
662 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
663 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
664
665 return( len );
666}
667
668/*
669 * Extension ::= SEQUENCE {
670 * extnID OBJECT IDENTIFIER,
671 * critical BOOLEAN DEFAULT FALSE,
672 * extnValue OCTET STRING
673 * -- contains the DER encoding of an ASN.1 value
674 * -- corresponding to the extension type identified
675 * -- by extnID
676 * }
677 */
678static int x509_write_extensions( unsigned char **p, unsigned char *start,
679 asn1_named_data *first )
680{
681 int ret;
682 size_t len = 0;
683 asn1_named_data *cur_ext = first;
684
685 while( cur_ext != NULL )
686 {
687 ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
688 cur_ext = cur_ext->next;
689 }
690
691 return( len );
692}
693
Paul Bakkercd358032013-09-09 12:08:11 +0200694int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000695{
696 int ret;
Paul Bakkerc70b9822013-04-07 22:00:46 +0200697 const char *sig_oid;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200698 size_t sig_oid_len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000699 unsigned char *c, *c2;
Paul Bakker3cac5e02012-02-16 14:08:06 +0000700 unsigned char hash[64];
701 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000702 unsigned char tmp_buf[2048];
Paul Bakker9397dcb2013-09-06 09:55:26 +0200703 size_t pub_len = 0, sig_len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000704 size_t len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000705
706 c = tmp_buf + 2048 - 1;
707
Paul Bakker15162a02013-09-06 19:27:21 +0200708 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200709
Paul Bakkere5eae762013-08-26 12:05:14 +0200710 if( len )
Paul Bakkerfde42702013-08-25 14:47:27 +0200711 {
Paul Bakkere5eae762013-08-26 12:05:14 +0200712 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
713 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200714
Paul Bakkere5eae762013-08-26 12:05:14 +0200715 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
716 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200717
Paul Bakker5f45e622013-09-09 12:02:36 +0200718 ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ,
719 OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200720
Paul Bakkere5eae762013-08-26 12:05:14 +0200721 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
722 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200723 }
724
Paul Bakkere5eae762013-08-26 12:05:14 +0200725 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000726 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) );
727
Manuel Pégourié-Gonnard5353a032013-09-11 12:14:26 +0200728 // TODO: use x509_write_rsa_pubkey() (pb: pub_len)
729 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &pk_rsa( *ctx->key )->E ) );
730 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &pk_rsa( *ctx->key )->N ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000731
732 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
733 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
734
735 if( c - tmp_buf < 1 )
736 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
737
Paul Bakker8eabfc12013-08-25 10:18:25 +0200738 /*
739 * AlgorithmIdentifier ::= SEQUENCE {
740 * algorithm OBJECT IDENTIFIER,
741 * parameters ANY DEFINED BY algorithm OPTIONAL }
742 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000743 *--c = 0;
744 pub_len += 1;
745
746 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
747 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_BIT_STRING ) );
748
Paul Bakker5f45e622013-09-09 12:02:36 +0200749 ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf,
750 OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000751
752 len += pub_len;
753 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) );
754 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
755
Paul Bakker9397dcb2013-09-06 09:55:26 +0200756 /*
757 * Subject ::= Name
758 */
759 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000760
Paul Bakker8eabfc12013-08-25 10:18:25 +0200761 /*
762 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
763 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000764 ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
765
766 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
767 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200768
Paul Bakker8eabfc12013-08-25 10:18:25 +0200769 md( md_info_from_type( ctx->md_alg ), c, len, hash );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000770
Manuel Pégourié-Gonnard5353a032013-09-11 12:14:26 +0200771 if( !pk_can_do( ctx->key, POLARSSL_PK_RSA ) )
772 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
773
774 // TODO: use pk_sign()
775 rsa_pkcs1_sign( pk_rsa( *ctx->key ), NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000776
777 // Generate correct OID
778 //
Manuel Pégourié-Gonnard5353a032013-09-11 12:14:26 +0200779 // TODO: use pk_info->type
Paul Bakker1c3853b2013-09-10 11:43:44 +0200780 ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid,
781 &sig_oid_len );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000782
Manuel Pégourié-Gonnard5353a032013-09-11 12:14:26 +0200783 // TODO: use pk_get_len()
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000784 c2 = buf + size - 1;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200785 ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len,
Manuel Pégourié-Gonnard5353a032013-09-11 12:14:26 +0200786 sig, pk_rsa( *ctx->key )->len ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200787
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000788 c2 -= len;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200789 memcpy( c2, c, len );
790
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000791 len += sig_len;
792 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
793 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
794
795 return( len );
796}
797
Paul Bakker9397dcb2013-09-06 09:55:26 +0200798int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size )
799{
800 int ret;
801 const char *sig_oid;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200802 size_t sig_oid_len = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200803 unsigned char *c, *c2;
804 unsigned char hash[64];
805 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
806 unsigned char tmp_buf[2048];
807 size_t sub_len = 0, pub_len = 0, sig_len = 0;
808 size_t len = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200809
810 c = tmp_buf + 2048 - 1;
811
812 // Generate correct OID
813 //
Paul Bakker1c3853b2013-09-10 11:43:44 +0200814 ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid,
815 &sig_oid_len );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200816 if( ret != 0 )
817 return( ret );
818
Paul Bakker15162a02013-09-06 19:27:21 +0200819 /*
820 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
821 */
822 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
823 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
824 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
825 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
826 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200827
828 /*
829 * SubjectPublicKeyInfo ::= SEQUENCE {
830 * algorithm AlgorithmIdentifier,
831 * subjectPublicKey BIT STRING }
832 */
833 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->subject_key->E ) );
834 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->subject_key->N ) );
835
836 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
837 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
838
839 if( c - tmp_buf < 1 )
840 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
841
842 *--c = 0;
843 pub_len += 1;
844
845 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
846 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_BIT_STRING ) );
847
Paul Bakker5f45e622013-09-09 12:02:36 +0200848 ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf,
849 OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200850
851 len += pub_len;
852 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) );
853 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
854
855 /*
856 * Subject ::= Name
857 */
858 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
859
860 /*
861 * Validity ::= SEQUENCE {
862 * notBefore Time,
863 * notAfter Time }
864 */
865 sub_len = 0;
866
867 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
868 X509_RFC5280_UTC_TIME_LEN ) );
869
870 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
871 X509_RFC5280_UTC_TIME_LEN ) );
872
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_CONSTRUCTED | ASN1_SEQUENCE ) );
876
877 /*
878 * Issuer ::= Name
879 */
880 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->issuer ) );
881
882 /*
883 * Signature ::= AlgorithmIdentifier
884 */
885 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf,
Paul Bakker5f45e622013-09-09 12:02:36 +0200886 sig_oid, strlen( sig_oid ) ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200887
888 /*
889 * Serial ::= INTEGER
890 */
891 ASN1_CHK_ADD( len, asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
892
893 /*
894 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
895 */
896 sub_len = 0;
897 ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) );
898 len += sub_len;
899 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
900 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) );
901
902 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
903 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
904
905 md( md_info_from_type( ctx->md_alg ), c, len, hash );
906
907 rsa_pkcs1_sign( ctx->issuer_key, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig );
908
909 c2 = buf + size - 1;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200910 ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len,
911 sig, ctx->issuer_key->len ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200912
913 c2 -= len;
914 memcpy( c2, c, len );
915
916 len += sig_len;
917 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
918 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
919
920 return( len );
921}
922
923#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
924#define PEM_END_CRT "-----END CERTIFICATE-----\n"
925
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200926#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n"
927#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n"
928
929#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n"
930#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n"
931
932#define PEM_BEGIN_PRIVATE_KEY "-----BEGIN RSA PRIVATE KEY-----\n"
933#define PEM_END_PRIVATE_KEY "-----END RSA PRIVATE KEY-----\n"
Paul Bakker135f1e92013-08-26 16:54:13 +0200934
935#if defined(POLARSSL_BASE64_C)
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200936static int x509write_pemify( const char *begin_str, const char *end_str,
937 const unsigned char *der_data, size_t der_len,
938 unsigned char *buf, size_t size )
Paul Bakker135f1e92013-08-26 16:54:13 +0200939{
940 int ret;
Paul Bakker135f1e92013-08-26 16:54:13 +0200941 unsigned char base_buf[4096];
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200942 unsigned char *c = base_buf, *p = buf;
943 size_t len = 0, olen = sizeof(base_buf);
Paul Bakker135f1e92013-08-26 16:54:13 +0200944
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200945 if( ( ret = base64_encode( base_buf, &olen, der_data, der_len ) ) != 0 )
Paul Bakker135f1e92013-08-26 16:54:13 +0200946 return( ret );
947
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200948 if( olen + strlen( begin_str ) + strlen( end_str ) +
Paul Bakker135f1e92013-08-26 16:54:13 +0200949 olen / 64 > size )
950 {
951 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
952 }
953
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200954 memcpy( p, begin_str, strlen( begin_str ) );
955 p += strlen( begin_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200956
957 while( olen )
958 {
959 len = ( olen > 64 ) ? 64 : olen;
960 memcpy( p, c, len );
961 olen -= len;
962 p += len;
963 c += len;
964 *p++ = '\n';
965 }
966
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200967 memcpy( p, end_str, strlen( end_str ) );
968 p += strlen( end_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200969
970 *p = '\0';
971
972 return( 0 );
973}
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200974
Paul Bakker9397dcb2013-09-06 09:55:26 +0200975int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size )
976{
977 int ret;
978 unsigned char output_buf[4096];
979
980 if( ( ret = x509write_crt_der( crt, output_buf,
981 sizeof(output_buf) ) ) < 0 )
982 {
983 return( ret );
984 }
985
986 if( ( ret = x509write_pemify( PEM_BEGIN_CRT, PEM_END_CRT,
987 output_buf + sizeof(output_buf) - 1 - ret,
988 ret, buf, size ) ) != 0 )
989 {
990 return( ret );
991 }
992
993 return( 0 );
994}
995
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200996int x509write_pubkey_pem( rsa_context *rsa, unsigned char *buf, size_t size )
997{
998 int ret;
999 unsigned char output_buf[4096];
1000
1001 if( ( ret = x509write_pubkey_der( rsa, output_buf,
1002 sizeof(output_buf) ) ) < 0 )
1003 {
1004 return( ret );
1005 }
1006
1007 if( ( ret = x509write_pemify( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
1008 output_buf + sizeof(output_buf) - 1 - ret,
1009 ret, buf, size ) ) != 0 )
1010 {
1011 return( ret );
1012 }
1013
1014 return( 0 );
1015}
1016
1017int x509write_key_pem( rsa_context *rsa, unsigned char *buf, size_t size )
1018{
1019 int ret;
1020 unsigned char output_buf[4096];
1021
1022 if( ( ret = x509write_key_der( rsa, output_buf,
1023 sizeof(output_buf) ) ) < 0 )
1024 {
1025 return( ret );
1026 }
1027
1028 if( ( ret = x509write_pemify( PEM_BEGIN_PRIVATE_KEY, PEM_END_PRIVATE_KEY,
1029 output_buf + sizeof(output_buf) - 1 - ret,
1030 ret, buf, size ) ) != 0 )
1031 {
1032 return( ret );
1033 }
1034
1035 return( 0 );
1036}
1037
Paul Bakkercd358032013-09-09 12:08:11 +02001038int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size )
Paul Bakkerf3df61a2013-08-26 17:22:23 +02001039{
1040 int ret;
1041 unsigned char output_buf[4096];
1042
1043 if( ( ret = x509write_csr_der( ctx, output_buf,
1044 sizeof(output_buf) ) ) < 0 )
1045 {
1046 return( ret );
1047 }
1048
1049 if( ( ret = x509write_pemify( PEM_BEGIN_CSR, PEM_END_CSR,
1050 output_buf + sizeof(output_buf) - 1 - ret,
1051 ret, buf, size ) ) != 0 )
1052 {
1053 return( ret );
1054 }
1055
1056 return( 0 );
1057}
Paul Bakker135f1e92013-08-26 16:54:13 +02001058#endif /* POLARSSL_BASE64_C */
1059
Paul Bakkerbdb912d2012-02-13 23:11:30 +00001060#endif