blob: 7c4ca33d5f2cdbbddf03f4736a0e8a89002de18b [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é-Gonnard5353a032013-09-11 12:14:26 +0200159// TODO: take a pk_context
160// TODO: return int
Paul Bakkercd358032013-09-09 12:08:11 +0200161void x509write_csr_set_rsa_key( x509write_csr *ctx, rsa_context *rsa )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200162{
Manuel Pégourié-Gonnard5353a032013-09-11 12:14:26 +0200163 // temporary
164 ctx->key = polarssl_malloc( sizeof( pk_context ) );
165
166 // TODO: check errors
167 pk_init_ctx( ctx->key, pk_info_from_type( POLARSSL_PK_RSA ) );
168 rsa_copy( pk_rsa( *ctx->key ), rsa );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200169}
170
Paul Bakkercd358032013-09-09 12:08:11 +0200171int x509write_csr_set_subject_name( x509write_csr *ctx, char *subject_name )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200172{
173 return x509write_string_to_names( &ctx->subject, subject_name );
174}
175
Paul Bakker15162a02013-09-06 19:27:21 +0200176/* The first byte of the value in the asn1_named_data structure is reserved
177 * to store the critical boolean for us
178 */
179static int x509_set_extension( asn1_named_data **head,
180 const char *oid, size_t oid_len,
181 int critical,
182 const unsigned char *val, size_t val_len )
Paul Bakkerfde42702013-08-25 14:47:27 +0200183{
Paul Bakkere5eae762013-08-26 12:05:14 +0200184 asn1_named_data *cur;
Paul Bakkere5eae762013-08-26 12:05:14 +0200185
Paul Bakker59ba59f2013-09-09 11:26:00 +0200186 if( ( cur = asn1_store_named_data( head, oid, oid_len,
187 NULL, val_len + 1 ) ) == NULL )
Paul Bakkere5eae762013-08-26 12:05:14 +0200188 {
Paul Bakker59ba59f2013-09-09 11:26:00 +0200189 return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
Paul Bakker1c0e5502013-08-26 13:41:01 +0200190 }
191
Paul Bakker15162a02013-09-06 19:27:21 +0200192 cur->val.p[0] = critical;
193 memcpy( cur->val.p + 1, val, val_len );
Paul Bakker1c0e5502013-08-26 13:41:01 +0200194
195 return( 0 );
196}
197
Paul Bakkercd358032013-09-09 12:08:11 +0200198int x509write_csr_set_extension( x509write_csr *ctx,
Paul Bakker15162a02013-09-06 19:27:21 +0200199 const char *oid, size_t oid_len,
200 const unsigned char *val, size_t val_len )
201{
202 return x509_set_extension( &ctx->extensions, oid, oid_len,
203 0, val, val_len );
204}
205
Paul Bakkercd358032013-09-09 12:08:11 +0200206int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200207{
208 unsigned char buf[4];
209 unsigned char *c;
210 int ret;
211
212 c = buf + 4;
213
Paul Bakker624d03a2013-08-26 14:12:57 +0200214 if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200215 return( ret );
216
217 ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE,
218 OID_SIZE( OID_KEY_USAGE ),
219 buf, 4 );
220 if( ret != 0 )
221 return( ret );
222
223 return( 0 );
224}
225
Paul Bakkercd358032013-09-09 12:08:11 +0200226int x509write_csr_set_ns_cert_type( x509write_csr *ctx,
227 unsigned char ns_cert_type )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200228{
229 unsigned char buf[4];
230 unsigned char *c;
231 int ret;
232
233 c = buf + 4;
234
235 if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
236 return( ret );
237
238 ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE,
239 OID_SIZE( OID_NS_CERT_TYPE ),
240 buf, 4 );
241 if( ret != 0 )
242 return( ret );
Paul Bakkere5eae762013-08-26 12:05:14 +0200243
244 return( 0 );
Paul Bakkerfde42702013-08-25 14:47:27 +0200245}
246
Paul Bakker9397dcb2013-09-06 09:55:26 +0200247void x509write_crt_init( x509write_cert *ctx )
248{
249 memset( ctx, 0, sizeof(x509write_cert) );
250
251 mpi_init( &ctx->serial );
252 ctx->version = X509_CRT_VERSION_3;
253}
254
255void x509write_crt_free( x509write_cert *ctx )
256{
Paul Bakker9397dcb2013-09-06 09:55:26 +0200257 mpi_free( &ctx->serial );
258
Paul Bakker5f45e622013-09-09 12:02:36 +0200259 asn1_free_named_data_list( &ctx->subject );
260 asn1_free_named_data_list( &ctx->issuer );
261 asn1_free_named_data_list( &ctx->extensions );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200262
Paul Bakkercd358032013-09-09 12:08:11 +0200263 memset( ctx, 0, sizeof(x509write_csr) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200264}
265
266void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg )
267{
268 ctx->md_alg = md_alg;
269}
270
271void x509write_crt_set_subject_key( x509write_cert *ctx, rsa_context *rsa )
272{
273 ctx->subject_key = rsa;
274}
275
276void x509write_crt_set_issuer_key( x509write_cert *ctx, rsa_context *rsa )
277{
278 ctx->issuer_key = rsa;
279}
280
281int x509write_crt_set_subject_name( x509write_cert *ctx, char *subject_name )
282{
283 return x509write_string_to_names( &ctx->subject, subject_name );
284}
285
286int x509write_crt_set_issuer_name( x509write_cert *ctx, char *issuer_name )
287{
288 return x509write_string_to_names( &ctx->issuer, issuer_name );
289}
290
291int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial )
292{
293 int ret;
294
295 if( ( ret = mpi_copy( &ctx->serial, serial ) ) != 0 )
296 return( ret );
297
298 return( 0 );
299}
300
301int x509write_crt_set_validity( x509write_cert *ctx, char *not_before,
302 char *not_after )
303{
304 if( strlen(not_before) != X509_RFC5280_UTC_TIME_LEN - 1 ||
305 strlen(not_after) != X509_RFC5280_UTC_TIME_LEN - 1 )
306 {
307 return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
308 }
309 strncpy( ctx->not_before, not_before, X509_RFC5280_UTC_TIME_LEN );
310 strncpy( ctx->not_after , not_after , X509_RFC5280_UTC_TIME_LEN );
311 ctx->not_before[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
312 ctx->not_after[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
313
314 return( 0 );
315}
316
Paul Bakker15162a02013-09-06 19:27:21 +0200317int x509write_crt_set_extension( x509write_cert *ctx,
318 const char *oid, size_t oid_len,
319 int critical,
320 const unsigned char *val, size_t val_len )
321{
322 return x509_set_extension( &ctx->extensions, oid, oid_len,
323 critical, val, val_len );
324}
325
326int x509write_crt_set_basic_constraints( x509write_cert *ctx,
327 int is_ca, int max_pathlen )
328{
329 int ret;
330 unsigned char buf[9];
331 unsigned char *c = buf + sizeof(buf);
332 size_t len = 0;
333
334 memset( buf, 0, sizeof(buf) );
335
336 if( is_ca && max_pathlen > 127 )
337 return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA );
338
339 if( is_ca )
340 {
341 if( max_pathlen >= 0 )
342 {
343 ASN1_CHK_ADD( len, asn1_write_int( &c, buf, max_pathlen ) );
344 }
345 ASN1_CHK_ADD( len, asn1_write_bool( &c, buf, 1 ) );
346 }
347
348 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
349 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
350
351 return x509write_crt_set_extension( ctx, OID_BASIC_CONSTRAINTS,
352 OID_SIZE( OID_BASIC_CONSTRAINTS ),
353 0, buf + sizeof(buf) - len, len );
354}
355
356int x509write_crt_set_subject_key_identifier( x509write_cert *ctx )
357{
358 int ret;
359 unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
360 unsigned char *c = buf + sizeof(buf);
361 size_t len = 0;
362
363 memset( buf, 0, sizeof(buf));
364 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, ctx->subject_key ) );
365
366 sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
367 c = buf + sizeof(buf) - 20;
368 len = 20;
369
370 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
371 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_OCTET_STRING ) );
372
373 return x509write_crt_set_extension( ctx, OID_SUBJECT_KEY_IDENTIFIER,
374 OID_SIZE( OID_SUBJECT_KEY_IDENTIFIER ),
375 0, buf + sizeof(buf) - len, len );
376}
377
378int x509write_crt_set_authority_key_identifier( x509write_cert *ctx )
379{
380 int ret;
381 unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
382 unsigned char *c = buf + sizeof(buf);
383 size_t len = 0;
384
385 memset( buf, 0, sizeof(buf));
386 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, ctx->issuer_key ) );
387
388 sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
389 c = buf + sizeof(buf) - 20;
390 len = 20;
391
392 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
393 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONTEXT_SPECIFIC | 0 ) );
394
395 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
396 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
397
398 return x509write_crt_set_extension( ctx, OID_AUTHORITY_KEY_IDENTIFIER,
399 OID_SIZE( OID_AUTHORITY_KEY_IDENTIFIER ),
400 0, buf + sizeof(buf) - len, len );
401}
402
Paul Bakker52be08c2013-09-09 12:37:54 +0200403int x509write_crt_set_key_usage( x509write_cert *ctx, unsigned char key_usage )
404{
405 unsigned char buf[4];
406 unsigned char *c;
407 int ret;
408
409 c = buf + 4;
410
411 if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
412 return( ret );
413
414 ret = x509write_crt_set_extension( ctx, OID_KEY_USAGE,
415 OID_SIZE( OID_KEY_USAGE ),
416 1, buf, 4 );
417 if( ret != 0 )
418 return( ret );
419
420 return( 0 );
421}
422
423int x509write_crt_set_ns_cert_type( x509write_cert *ctx,
424 unsigned char ns_cert_type )
425{
426 unsigned char buf[4];
427 unsigned char *c;
428 int ret;
429
430 c = buf + 4;
431
432 if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
433 return( ret );
434
435 ret = x509write_crt_set_extension( ctx, OID_NS_CERT_TYPE,
436 OID_SIZE( OID_NS_CERT_TYPE ),
437 0, buf, 4 );
438 if( ret != 0 )
439 return( ret );
440
441 return( 0 );
442}
443
Paul Bakker82e29452013-08-25 11:01:31 +0200444int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000445{
446 int ret;
447 unsigned char *c;
448 size_t len = 0;
449
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200450 c = buf + size;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000451
Paul Bakker15162a02013-09-06 19:27:21 +0200452 ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, rsa ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000453
454 if( c - buf < 1 )
455 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
456
Paul Bakker8eabfc12013-08-25 10:18:25 +0200457 /*
458 * SubjectPublicKeyInfo ::= SEQUENCE {
459 * algorithm AlgorithmIdentifier,
460 * subjectPublicKey BIT STRING }
461 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000462 *--c = 0;
463 len += 1;
464
465 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
466 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) );
467
Paul Bakker5f45e622013-09-09 12:02:36 +0200468 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf,
469 OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000470
471 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
472 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
473
474 return( len );
475}
476
Paul Bakker82e29452013-08-25 11:01:31 +0200477int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000478{
479 int ret;
480 unsigned char *c;
481 size_t len = 0;
482
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200483 c = buf + size;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000484
485 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) );
486 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) );
487 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) );
488 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) );
489 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) );
490 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) );
491 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) );
492 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) );
493 ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) );
494
495 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
496 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
497
498 // TODO: Make NON RSA Specific variant later on
499/* *--c = 0;
500 len += 1;
501
502 len += asn1_write_len( &c, len);
503 len += asn1_write_tag( &c, ASN1_BIT_STRING );
504
505 len += asn1_write_oid( &c, OID_PKCS1_RSA );
506
507 len += asn1_write_int( &c, 0 );
508
509 len += asn1_write_len( &c, len);
510 len += asn1_write_tag( &c, ASN1_CONSTRUCTED | ASN1_SEQUENCE );*/
511
512/* for(i = 0; i < len; ++i)
513 {
514 if (i % 16 == 0 ) printf("\n");
515 printf("%02x ", c[i]);
516 }
517 printf("\n");*/
518
519 return( len );
520}
521
Paul Bakker9397dcb2013-09-06 09:55:26 +0200522/*
523 * RelativeDistinguishedName ::=
524 * SET OF AttributeTypeAndValue
525 *
526 * AttributeTypeAndValue ::= SEQUENCE {
527 * type AttributeType,
528 * value AttributeValue }
529 *
530 * AttributeType ::= OBJECT IDENTIFIER
531 *
532 * AttributeValue ::= ANY DEFINED BY AttributeType
533 */
Paul Bakker5f45e622013-09-09 12:02:36 +0200534static int x509_write_name( unsigned char **p, unsigned char *start,
535 const char *oid, size_t oid_len,
536 const unsigned char *name, size_t name_len )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000537{
538 int ret;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000539 size_t len = 0;
540
Paul Bakker05888152012-02-16 10:26:57 +0000541 // Write PrintableString for all except OID_PKCS9_EMAIL
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000542 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200543 if( OID_SIZE( OID_PKCS9_EMAIL ) == oid_len &&
544 memcmp( oid, OID_PKCS9_EMAIL, oid_len ) == 0 )
Paul Bakker05888152012-02-16 10:26:57 +0000545 {
Paul Bakker5f45e622013-09-09 12:02:36 +0200546 ASN1_CHK_ADD( len, asn1_write_ia5_string( p, start,
547 (const char *) name,
548 name_len ) );
Paul Bakker05888152012-02-16 10:26:57 +0000549 }
550 else
Paul Bakker5f45e622013-09-09 12:02:36 +0200551 {
552 ASN1_CHK_ADD( len, asn1_write_printable_string( p, start,
553 (const char *) name,
554 name_len ) );
555 }
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000556
557 // Write OID
558 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200559 ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000560
Paul Bakker5f45e622013-09-09 12:02:36 +0200561 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000562 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
563
564 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
565 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) );
566
567 return( len );
568}
569
Paul Bakker9397dcb2013-09-06 09:55:26 +0200570static int x509_write_names( unsigned char **p, unsigned char *start,
Paul Bakker5f45e622013-09-09 12:02:36 +0200571 asn1_named_data *first )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200572{
573 int ret;
574 size_t len = 0;
Paul Bakker5f45e622013-09-09 12:02:36 +0200575 asn1_named_data *cur = first;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200576
577 while( cur != NULL )
578 {
Paul Bakker5f45e622013-09-09 12:02:36 +0200579 ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p,
580 cur->oid.len,
581 cur->val.p, cur->val.len ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200582 cur = cur->next;
583 }
584
585 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
586 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
587
588 return( len );
589}
590
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200591static int x509_write_sig( unsigned char **p, unsigned char *start,
Paul Bakker1c3853b2013-09-10 11:43:44 +0200592 const char *oid, size_t oid_len,
593 unsigned char *sig, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000594{
595 int ret;
596 size_t len = 0;
597
598 if( *p - start < (int) size + 1 )
599 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
600
601 len = size;
602 (*p) -= len;
603 memcpy( *p, sig, len );
604
605 *--(*p) = 0;
606 len += 1;
607
608 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
609 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
610
611 // Write OID
612 //
Paul Bakker5f45e622013-09-09 12:02:36 +0200613 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid,
Paul Bakker1c3853b2013-09-10 11:43:44 +0200614 oid_len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000615
616 return( len );
617}
618
Paul Bakker9397dcb2013-09-06 09:55:26 +0200619static int x509_write_time( unsigned char **p, unsigned char *start,
620 const char *time, size_t size )
621{
622 int ret;
623 size_t len = 0;
624
Paul Bakker9c208aa2013-09-08 15:44:31 +0200625 /*
626 * write ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
627 */
628 if( time[0] == '2' && time[1] == '0' && time [2] < '5' )
629 {
630 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
631 (const unsigned char *) time + 2,
632 size - 2 ) );
633 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
634 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_UTC_TIME ) );
635 }
636 else
637 {
638 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
639 (const unsigned char *) time,
640 size ) );
641 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
642 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_GENERALIZED_TIME ) );
643 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200644
645 return( len );
646}
647
Paul Bakker15162a02013-09-06 19:27:21 +0200648static int x509_write_extension( unsigned char **p, unsigned char *start,
649 asn1_named_data *ext )
650{
651 int ret;
652 size_t len = 0;
653
654 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->val.p + 1,
655 ext->val.len - 1 ) );
656 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->val.len - 1 ) );
657 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) );
658
659 if( ext->val.p[0] != 0 )
660 {
661 ASN1_CHK_ADD( len, asn1_write_bool( p, start, 1 ) );
662 }
663
664 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->oid.p,
665 ext->oid.len ) );
666 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->oid.len ) );
667 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) );
668
669 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
670 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
671
672 return( len );
673}
674
675/*
676 * Extension ::= SEQUENCE {
677 * extnID OBJECT IDENTIFIER,
678 * critical BOOLEAN DEFAULT FALSE,
679 * extnValue OCTET STRING
680 * -- contains the DER encoding of an ASN.1 value
681 * -- corresponding to the extension type identified
682 * -- by extnID
683 * }
684 */
685static int x509_write_extensions( unsigned char **p, unsigned char *start,
686 asn1_named_data *first )
687{
688 int ret;
689 size_t len = 0;
690 asn1_named_data *cur_ext = first;
691
692 while( cur_ext != NULL )
693 {
694 ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
695 cur_ext = cur_ext->next;
696 }
697
698 return( len );
699}
700
Paul Bakkercd358032013-09-09 12:08:11 +0200701int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000702{
703 int ret;
Paul Bakkerc70b9822013-04-07 22:00:46 +0200704 const char *sig_oid;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200705 size_t sig_oid_len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000706 unsigned char *c, *c2;
Paul Bakker3cac5e02012-02-16 14:08:06 +0000707 unsigned char hash[64];
708 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000709 unsigned char tmp_buf[2048];
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200710 size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000711 size_t len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000712
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200713 /*
714 * Prepare data to be signed in tmp_buf
715 */
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200716 c = tmp_buf + sizeof( tmp_buf );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000717
Paul Bakker15162a02013-09-06 19:27:21 +0200718 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200719
Paul Bakkere5eae762013-08-26 12:05:14 +0200720 if( len )
Paul Bakkerfde42702013-08-25 14:47:27 +0200721 {
Paul Bakkere5eae762013-08-26 12:05:14 +0200722 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
723 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200724
Paul Bakkere5eae762013-08-26 12:05:14 +0200725 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
726 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200727
Paul Bakker5f45e622013-09-09 12:02:36 +0200728 ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ,
729 OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200730
Paul Bakkere5eae762013-08-26 12:05:14 +0200731 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
732 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200733 }
734
Paul Bakkere5eae762013-08-26 12:05:14 +0200735 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000736 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) );
737
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200738 if( !pk_can_do( ctx->key, POLARSSL_PK_RSA ) )
739 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnard6dcf0bf2013-09-11 13:09:04 +0200740 ASN1_CHK_ADD( pub_len, x509write_pubkey_der( pk_rsa( *ctx->key ),
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200741 tmp_buf, c - tmp_buf ) );
Manuel Pégourié-Gonnard6dcf0bf2013-09-11 13:09:04 +0200742 c -= pub_len;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000743 len += pub_len;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000744
Paul Bakker9397dcb2013-09-06 09:55:26 +0200745 /*
746 * Subject ::= Name
747 */
748 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000749
Paul Bakker8eabfc12013-08-25 10:18:25 +0200750 /*
751 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
752 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000753 ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
754
755 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
756 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200757
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200758 /*
759 * Prepare signature
760 */
Paul Bakker8eabfc12013-08-25 10:18:25 +0200761 md( md_info_from_type( ctx->md_alg ), c, len, hash );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000762
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200763 if( ( ret = pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,
764 NULL, NULL ) ) != 0 ||
765 ( ret = oid_get_oid_by_sig_alg( pk_get_type( ctx->key ), ctx->md_alg,
766 &sig_oid, &sig_oid_len ) ) != 0 )
767 {
768 return( ret );
769 }
Manuel Pégourié-Gonnard5353a032013-09-11 12:14:26 +0200770
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200771 /*
772 * Write data to output buffer
773 */
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200774 c2 = buf + size;
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200775 ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf,
776 sig_oid, sig_oid_len, sig, sig_len ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200777
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000778 c2 -= len;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200779 memcpy( c2, c, len );
780
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200781 len += sig_and_oid_len;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000782 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
783 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
784
785 return( len );
786}
787
Paul Bakker9397dcb2013-09-06 09:55:26 +0200788int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size )
789{
790 int ret;
791 const char *sig_oid;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200792 size_t sig_oid_len = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200793 unsigned char *c, *c2;
794 unsigned char hash[64];
795 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
796 unsigned char tmp_buf[2048];
797 size_t sub_len = 0, pub_len = 0, sig_len = 0;
798 size_t len = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200799
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200800 c = tmp_buf + sizeof( tmp_buf );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200801
802 // Generate correct OID
803 //
Paul Bakker1c3853b2013-09-10 11:43:44 +0200804 ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid,
805 &sig_oid_len );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200806 if( ret != 0 )
807 return( ret );
808
Paul Bakker15162a02013-09-06 19:27:21 +0200809 /*
810 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
811 */
812 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
813 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
814 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
815 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
816 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200817
818 /*
Manuel Pégourié-Gonnard6dcf0bf2013-09-11 13:09:04 +0200819 * SubjectPublicKeyInfo
Paul Bakker9397dcb2013-09-06 09:55:26 +0200820 */
Manuel Pégourié-Gonnard6dcf0bf2013-09-11 13:09:04 +0200821 ASN1_CHK_ADD( pub_len, x509write_pubkey_der( ctx->subject_key,
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200822 tmp_buf, c - tmp_buf ) );
Manuel Pégourié-Gonnard6dcf0bf2013-09-11 13:09:04 +0200823 c -= pub_len;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200824 len += pub_len;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200825
826 /*
827 * Subject ::= Name
828 */
829 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
830
831 /*
832 * Validity ::= SEQUENCE {
833 * notBefore Time,
834 * notAfter Time }
835 */
836 sub_len = 0;
837
838 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
839 X509_RFC5280_UTC_TIME_LEN ) );
840
841 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
842 X509_RFC5280_UTC_TIME_LEN ) );
843
844 len += sub_len;
845 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
846 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
847
848 /*
849 * Issuer ::= Name
850 */
851 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->issuer ) );
852
853 /*
854 * Signature ::= AlgorithmIdentifier
855 */
856 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf,
Paul Bakker5f45e622013-09-09 12:02:36 +0200857 sig_oid, strlen( sig_oid ) ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200858
859 /*
860 * Serial ::= INTEGER
861 */
862 ASN1_CHK_ADD( len, asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
863
864 /*
865 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
866 */
867 sub_len = 0;
868 ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) );
869 len += sub_len;
870 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
871 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) );
872
873 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
874 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
875
876 md( md_info_from_type( ctx->md_alg ), c, len, hash );
877
878 rsa_pkcs1_sign( ctx->issuer_key, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig );
879
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200880 c2 = buf + size;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200881 ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len,
882 sig, ctx->issuer_key->len ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200883
884 c2 -= len;
885 memcpy( c2, c, len );
886
887 len += sig_len;
888 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
889 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
890
891 return( len );
892}
893
894#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
895#define PEM_END_CRT "-----END CERTIFICATE-----\n"
896
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200897#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n"
898#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n"
899
900#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n"
901#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n"
902
903#define PEM_BEGIN_PRIVATE_KEY "-----BEGIN RSA PRIVATE KEY-----\n"
904#define PEM_END_PRIVATE_KEY "-----END RSA PRIVATE KEY-----\n"
Paul Bakker135f1e92013-08-26 16:54:13 +0200905
906#if defined(POLARSSL_BASE64_C)
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200907static int x509write_pemify( const char *begin_str, const char *end_str,
908 const unsigned char *der_data, size_t der_len,
909 unsigned char *buf, size_t size )
Paul Bakker135f1e92013-08-26 16:54:13 +0200910{
911 int ret;
Paul Bakker135f1e92013-08-26 16:54:13 +0200912 unsigned char base_buf[4096];
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200913 unsigned char *c = base_buf, *p = buf;
914 size_t len = 0, olen = sizeof(base_buf);
Paul Bakker135f1e92013-08-26 16:54:13 +0200915
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200916 if( ( ret = base64_encode( base_buf, &olen, der_data, der_len ) ) != 0 )
Paul Bakker135f1e92013-08-26 16:54:13 +0200917 return( ret );
918
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200919 if( olen + strlen( begin_str ) + strlen( end_str ) +
Paul Bakker135f1e92013-08-26 16:54:13 +0200920 olen / 64 > size )
921 {
922 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
923 }
924
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200925 memcpy( p, begin_str, strlen( begin_str ) );
926 p += strlen( begin_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200927
928 while( olen )
929 {
930 len = ( olen > 64 ) ? 64 : olen;
931 memcpy( p, c, len );
932 olen -= len;
933 p += len;
934 c += len;
935 *p++ = '\n';
936 }
937
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200938 memcpy( p, end_str, strlen( end_str ) );
939 p += strlen( end_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200940
941 *p = '\0';
942
943 return( 0 );
944}
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200945
Paul Bakker9397dcb2013-09-06 09:55:26 +0200946int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size )
947{
948 int ret;
949 unsigned char output_buf[4096];
950
951 if( ( ret = x509write_crt_der( crt, output_buf,
952 sizeof(output_buf) ) ) < 0 )
953 {
954 return( ret );
955 }
956
957 if( ( ret = x509write_pemify( PEM_BEGIN_CRT, PEM_END_CRT,
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200958 output_buf + sizeof(output_buf) - ret,
Paul Bakker9397dcb2013-09-06 09:55:26 +0200959 ret, buf, size ) ) != 0 )
960 {
961 return( ret );
962 }
963
964 return( 0 );
965}
966
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200967int x509write_pubkey_pem( rsa_context *rsa, unsigned char *buf, size_t size )
968{
969 int ret;
970 unsigned char output_buf[4096];
971
972 if( ( ret = x509write_pubkey_der( rsa, output_buf,
973 sizeof(output_buf) ) ) < 0 )
974 {
975 return( ret );
976 }
977
978 if( ( ret = x509write_pemify( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200979 output_buf + sizeof(output_buf) - ret,
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200980 ret, buf, size ) ) != 0 )
981 {
982 return( ret );
983 }
984
985 return( 0 );
986}
987
988int x509write_key_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_key_der( rsa, output_buf,
994 sizeof(output_buf) ) ) < 0 )
995 {
996 return( ret );
997 }
998
999 if( ( ret = x509write_pemify( PEM_BEGIN_PRIVATE_KEY, PEM_END_PRIVATE_KEY,
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +02001000 output_buf + sizeof(output_buf) - ret,
Paul Bakkerf3df61a2013-08-26 17:22:23 +02001001 ret, buf, size ) ) != 0 )
1002 {
1003 return( ret );
1004 }
1005
1006 return( 0 );
1007}
1008
Paul Bakkercd358032013-09-09 12:08:11 +02001009int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size )
Paul Bakkerf3df61a2013-08-26 17:22:23 +02001010{
1011 int ret;
1012 unsigned char output_buf[4096];
1013
1014 if( ( ret = x509write_csr_der( ctx, output_buf,
1015 sizeof(output_buf) ) ) < 0 )
1016 {
1017 return( ret );
1018 }
1019
1020 if( ( ret = x509write_pemify( PEM_BEGIN_CSR, PEM_END_CSR,
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +02001021 output_buf + sizeof(output_buf) - ret,
Paul Bakkerf3df61a2013-08-26 17:22:23 +02001022 ret, buf, size ) ) != 0 )
1023 {
1024 return( ret );
1025 }
1026
1027 return( 0 );
1028}
Paul Bakker135f1e92013-08-26 16:54:13 +02001029#endif /* POLARSSL_BASE64_C */
1030
Paul Bakkerbdb912d2012-02-13 23:11:30 +00001031#endif