blob: 5c968412fac35c5f2554fdee2fbfbc73c31cca2b [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];
Paul Bakker9397dcb2013-09-06 09:55:26 +0200710 size_t pub_len = 0, sig_len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000711 size_t len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000712
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200713 c = tmp_buf + sizeof( tmp_buf );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000714
Paul Bakker15162a02013-09-06 19:27:21 +0200715 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200716
Paul Bakkere5eae762013-08-26 12:05:14 +0200717 if( len )
Paul Bakkerfde42702013-08-25 14:47:27 +0200718 {
Paul Bakkere5eae762013-08-26 12:05:14 +0200719 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
720 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
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_SET ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200724
Paul Bakker5f45e622013-09-09 12:02:36 +0200725 ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ,
726 OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200727
Paul Bakkere5eae762013-08-26 12:05:14 +0200728 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
729 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200730 }
731
Paul Bakkere5eae762013-08-26 12:05:14 +0200732 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000733 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) );
734
Manuel Pégourié-Gonnard6dcf0bf2013-09-11 13:09:04 +0200735 ASN1_CHK_ADD( pub_len, x509write_pubkey_der( pk_rsa( *ctx->key ),
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200736 tmp_buf, c - tmp_buf ) );
Manuel Pégourié-Gonnard6dcf0bf2013-09-11 13:09:04 +0200737 c -= pub_len;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000738 len += pub_len;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000739
Paul Bakker9397dcb2013-09-06 09:55:26 +0200740 /*
741 * Subject ::= Name
742 */
743 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000744
Paul Bakker8eabfc12013-08-25 10:18:25 +0200745 /*
746 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
747 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000748 ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
749
750 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
751 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200752
Paul Bakker8eabfc12013-08-25 10:18:25 +0200753 md( md_info_from_type( ctx->md_alg ), c, len, hash );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000754
Manuel Pégourié-Gonnard5353a032013-09-11 12:14:26 +0200755 if( !pk_can_do( ctx->key, POLARSSL_PK_RSA ) )
756 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
757
758 // TODO: use pk_sign()
759 rsa_pkcs1_sign( pk_rsa( *ctx->key ), NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000760
761 // Generate correct OID
762 //
Manuel Pégourié-Gonnard5353a032013-09-11 12:14:26 +0200763 // TODO: use pk_info->type
Paul Bakker1c3853b2013-09-10 11:43:44 +0200764 ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid,
765 &sig_oid_len );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000766
Manuel Pégourié-Gonnard5353a032013-09-11 12:14:26 +0200767 // TODO: use pk_get_len()
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200768 c2 = buf + size;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200769 ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len,
Manuel Pégourié-Gonnard5353a032013-09-11 12:14:26 +0200770 sig, pk_rsa( *ctx->key )->len ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200771
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000772 c2 -= len;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200773 memcpy( c2, c, len );
774
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000775 len += sig_len;
776 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
777 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
778
779 return( len );
780}
781
Paul Bakker9397dcb2013-09-06 09:55:26 +0200782int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size )
783{
784 int ret;
785 const char *sig_oid;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200786 size_t sig_oid_len = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200787 unsigned char *c, *c2;
788 unsigned char hash[64];
789 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
790 unsigned char tmp_buf[2048];
791 size_t sub_len = 0, pub_len = 0, sig_len = 0;
792 size_t len = 0;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200793
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200794 c = tmp_buf + sizeof( tmp_buf );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200795
796 // Generate correct OID
797 //
Paul Bakker1c3853b2013-09-10 11:43:44 +0200798 ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid,
799 &sig_oid_len );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200800 if( ret != 0 )
801 return( ret );
802
Paul Bakker15162a02013-09-06 19:27:21 +0200803 /*
804 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
805 */
806 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
807 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
808 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
809 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
810 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200811
812 /*
Manuel Pégourié-Gonnard6dcf0bf2013-09-11 13:09:04 +0200813 * SubjectPublicKeyInfo
Paul Bakker9397dcb2013-09-06 09:55:26 +0200814 */
Manuel Pégourié-Gonnard6dcf0bf2013-09-11 13:09:04 +0200815 ASN1_CHK_ADD( pub_len, x509write_pubkey_der( ctx->subject_key,
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200816 tmp_buf, c - tmp_buf ) );
Manuel Pégourié-Gonnard6dcf0bf2013-09-11 13:09:04 +0200817 c -= pub_len;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200818 len += pub_len;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200819
820 /*
821 * Subject ::= Name
822 */
823 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
824
825 /*
826 * Validity ::= SEQUENCE {
827 * notBefore Time,
828 * notAfter Time }
829 */
830 sub_len = 0;
831
832 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
833 X509_RFC5280_UTC_TIME_LEN ) );
834
835 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
836 X509_RFC5280_UTC_TIME_LEN ) );
837
838 len += sub_len;
839 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
840 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
841
842 /*
843 * Issuer ::= Name
844 */
845 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->issuer ) );
846
847 /*
848 * Signature ::= AlgorithmIdentifier
849 */
850 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf,
Paul Bakker5f45e622013-09-09 12:02:36 +0200851 sig_oid, strlen( sig_oid ) ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200852
853 /*
854 * Serial ::= INTEGER
855 */
856 ASN1_CHK_ADD( len, asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
857
858 /*
859 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
860 */
861 sub_len = 0;
862 ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) );
863 len += sub_len;
864 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
865 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) );
866
867 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
868 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
869
870 md( md_info_from_type( ctx->md_alg ), c, len, hash );
871
872 rsa_pkcs1_sign( ctx->issuer_key, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig );
873
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200874 c2 = buf + size;
Paul Bakker1c3853b2013-09-10 11:43:44 +0200875 ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len,
876 sig, ctx->issuer_key->len ) );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200877
878 c2 -= len;
879 memcpy( c2, c, len );
880
881 len += sig_len;
882 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
883 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
884
885 return( len );
886}
887
888#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
889#define PEM_END_CRT "-----END CERTIFICATE-----\n"
890
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200891#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n"
892#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n"
893
894#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n"
895#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n"
896
897#define PEM_BEGIN_PRIVATE_KEY "-----BEGIN RSA PRIVATE KEY-----\n"
898#define PEM_END_PRIVATE_KEY "-----END RSA PRIVATE KEY-----\n"
Paul Bakker135f1e92013-08-26 16:54:13 +0200899
900#if defined(POLARSSL_BASE64_C)
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200901static int x509write_pemify( const char *begin_str, const char *end_str,
902 const unsigned char *der_data, size_t der_len,
903 unsigned char *buf, size_t size )
Paul Bakker135f1e92013-08-26 16:54:13 +0200904{
905 int ret;
Paul Bakker135f1e92013-08-26 16:54:13 +0200906 unsigned char base_buf[4096];
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200907 unsigned char *c = base_buf, *p = buf;
908 size_t len = 0, olen = sizeof(base_buf);
Paul Bakker135f1e92013-08-26 16:54:13 +0200909
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200910 if( ( ret = base64_encode( base_buf, &olen, der_data, der_len ) ) != 0 )
Paul Bakker135f1e92013-08-26 16:54:13 +0200911 return( ret );
912
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200913 if( olen + strlen( begin_str ) + strlen( end_str ) +
Paul Bakker135f1e92013-08-26 16:54:13 +0200914 olen / 64 > size )
915 {
916 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
917 }
918
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200919 memcpy( p, begin_str, strlen( begin_str ) );
920 p += strlen( begin_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200921
922 while( olen )
923 {
924 len = ( olen > 64 ) ? 64 : olen;
925 memcpy( p, c, len );
926 olen -= len;
927 p += len;
928 c += len;
929 *p++ = '\n';
930 }
931
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200932 memcpy( p, end_str, strlen( end_str ) );
933 p += strlen( end_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200934
935 *p = '\0';
936
937 return( 0 );
938}
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200939
Paul Bakker9397dcb2013-09-06 09:55:26 +0200940int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size )
941{
942 int ret;
943 unsigned char output_buf[4096];
944
945 if( ( ret = x509write_crt_der( crt, output_buf,
946 sizeof(output_buf) ) ) < 0 )
947 {
948 return( ret );
949 }
950
951 if( ( ret = x509write_pemify( PEM_BEGIN_CRT, PEM_END_CRT,
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200952 output_buf + sizeof(output_buf) - ret,
Paul Bakker9397dcb2013-09-06 09:55:26 +0200953 ret, buf, size ) ) != 0 )
954 {
955 return( ret );
956 }
957
958 return( 0 );
959}
960
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200961int x509write_pubkey_pem( rsa_context *rsa, unsigned char *buf, size_t size )
962{
963 int ret;
964 unsigned char output_buf[4096];
965
966 if( ( ret = x509write_pubkey_der( rsa, output_buf,
967 sizeof(output_buf) ) ) < 0 )
968 {
969 return( ret );
970 }
971
972 if( ( ret = x509write_pemify( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200973 output_buf + sizeof(output_buf) - ret,
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200974 ret, buf, size ) ) != 0 )
975 {
976 return( ret );
977 }
978
979 return( 0 );
980}
981
982int x509write_key_pem( rsa_context *rsa, unsigned char *buf, size_t size )
983{
984 int ret;
985 unsigned char output_buf[4096];
986
987 if( ( ret = x509write_key_der( rsa, output_buf,
988 sizeof(output_buf) ) ) < 0 )
989 {
990 return( ret );
991 }
992
993 if( ( ret = x509write_pemify( PEM_BEGIN_PRIVATE_KEY, PEM_END_PRIVATE_KEY,
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +0200994 output_buf + sizeof(output_buf) - ret,
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200995 ret, buf, size ) ) != 0 )
996 {
997 return( ret );
998 }
999
1000 return( 0 );
1001}
1002
Paul Bakkercd358032013-09-09 12:08:11 +02001003int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size )
Paul Bakkerf3df61a2013-08-26 17:22:23 +02001004{
1005 int ret;
1006 unsigned char output_buf[4096];
1007
1008 if( ( ret = x509write_csr_der( ctx, output_buf,
1009 sizeof(output_buf) ) ) < 0 )
1010 {
1011 return( ret );
1012 }
1013
1014 if( ( ret = x509write_pemify( PEM_BEGIN_CSR, PEM_END_CSR,
Manuel Pégourié-Gonnard27d87fa2013-09-11 17:33:28 +02001015 output_buf + sizeof(output_buf) - ret,
Paul Bakkerf3df61a2013-08-26 17:22:23 +02001016 ret, buf, size ) ) != 0 )
1017 {
1018 return( ret );
1019 }
1020
1021 return( 0 );
1022}
Paul Bakker135f1e92013-08-26 16:54:13 +02001023#endif /* POLARSSL_BASE64_C */
1024
Paul Bakkerbdb912d2012-02-13 23:11:30 +00001025#endif