blob: 7e04e1206810f2d41d868e30201f55113ee12e1f [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 Bakker135f1e92013-08-26 16:54:13 +020036#if defined(POLARSSL_BASE64_C)
37#include "polarssl/base64.h"
38#endif
39
Paul Bakker8eabfc12013-08-25 10:18:25 +020040#if defined(POLARSSL_MEMORY_C)
41#include "polarssl/memory.h"
42#else
43#include <stdlib.h>
44#define polarssl_malloc malloc
45#define polarssl_free free
46#endif
47
Paul Bakker82e29452013-08-25 11:01:31 +020048void x509write_csr_init( x509_csr *ctx )
Paul Bakker8eabfc12013-08-25 10:18:25 +020049{
Paul Bakker82e29452013-08-25 11:01:31 +020050 memset( ctx, 0, sizeof(x509_csr) );
Paul Bakker8eabfc12013-08-25 10:18:25 +020051}
52
Paul Bakker82e29452013-08-25 11:01:31 +020053void x509write_csr_free( x509_csr *ctx )
Paul Bakker8eabfc12013-08-25 10:18:25 +020054{
55 x509_req_name *cur;
Paul Bakkere5eae762013-08-26 12:05:14 +020056 asn1_named_data *cur_ext;
Paul Bakker8eabfc12013-08-25 10:18:25 +020057
58 while( ( cur = ctx->subject ) != NULL )
59 {
60 ctx->subject = cur->next;
61 polarssl_free( cur );
62 }
63
Paul Bakkere5eae762013-08-26 12:05:14 +020064 while( ( cur_ext = ctx->extensions ) != NULL )
65 {
66 ctx->extensions = cur_ext->next;
67 asn1_free_named_data( cur_ext );
68 polarssl_free( cur_ext );
69 }
70
Paul Bakker82e29452013-08-25 11:01:31 +020071 memset( ctx, 0, sizeof(x509_csr) );
Paul Bakker8eabfc12013-08-25 10:18:25 +020072}
73
Paul Bakker82e29452013-08-25 11:01:31 +020074void x509write_csr_set_md_alg( x509_csr *ctx, md_type_t md_alg )
Paul Bakker8eabfc12013-08-25 10:18:25 +020075{
76 ctx->md_alg = md_alg;
77}
78
Paul Bakker82e29452013-08-25 11:01:31 +020079void x509write_csr_set_rsa_key( x509_csr *ctx, rsa_context *rsa )
Paul Bakker8eabfc12013-08-25 10:18:25 +020080{
81 ctx->rsa = rsa;
82}
83
Paul Bakker82e29452013-08-25 11:01:31 +020084int x509write_csr_set_subject_name( x509_csr *ctx, char *subject_name )
Paul Bakker8eabfc12013-08-25 10:18:25 +020085{
86 int ret = 0;
87 char *s = subject_name, *c = s;
88 char *end = s + strlen( s );
89 char *oid = NULL;
90 int in_tag = 1;
Paul Bakker21307962013-08-25 10:33:27 +020091 x509_req_name *cur;
Paul Bakker8eabfc12013-08-25 10:18:25 +020092
93 while( ctx->subject )
94 {
95 cur = ctx->subject;
96 ctx->subject = ctx->subject->next;
97 polarssl_free( cur );
98 }
99
100 while( c <= end )
101 {
102 if( in_tag && *c == '=' )
103 {
104 if( memcmp( s, "CN", 2 ) == 0 && c - s == 2 )
105 oid = OID_AT_CN;
106 else if( memcmp( s, "C", 1 ) == 0 && c - s == 1 )
107 oid = OID_AT_COUNTRY;
108 else if( memcmp( s, "O", 1 ) == 0 && c - s == 1 )
109 oid = OID_AT_ORGANIZATION;
110 else if( memcmp( s, "L", 1 ) == 0 && c - s == 1 )
111 oid = OID_AT_LOCALITY;
112 else if( memcmp( s, "R", 1 ) == 0 && c - s == 1 )
113 oid = OID_PKCS9_EMAIL;
114 else if( memcmp( s, "OU", 2 ) == 0 && c - s == 2 )
115 oid = OID_AT_ORG_UNIT;
116 else if( memcmp( s, "ST", 2 ) == 0 && c - s == 2 )
117 oid = OID_AT_STATE;
118 else
119 {
Paul Bakker0e06c0f2013-08-25 11:21:30 +0200120 ret = POLARSSL_ERR_X509WRITE_UNKNOWN_OID;
Paul Bakker8eabfc12013-08-25 10:18:25 +0200121 goto exit;
122 }
123
124 s = c + 1;
125 in_tag = 0;
126 }
127
128 if( !in_tag && ( *c == ',' || c == end ) )
129 {
130 if( c - s > 127 )
131 {
Paul Bakker0e06c0f2013-08-25 11:21:30 +0200132 ret = POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA;
Paul Bakker8eabfc12013-08-25 10:18:25 +0200133 goto exit;
134 }
135
Paul Bakker21307962013-08-25 10:33:27 +0200136 cur = polarssl_malloc( sizeof(x509_req_name) );
Paul Bakker8eabfc12013-08-25 10:18:25 +0200137
138 if( cur == NULL )
139 {
Paul Bakker0e06c0f2013-08-25 11:21:30 +0200140 ret = POLARSSL_ERR_X509WRITE_MALLOC_FAILED;
Paul Bakker8eabfc12013-08-25 10:18:25 +0200141 goto exit;
142 }
143
144 memset( cur, 0, sizeof(x509_req_name) );
145
Paul Bakker21307962013-08-25 10:33:27 +0200146 cur->next = ctx->subject;
147 ctx->subject = cur;
148
Paul Bakker8eabfc12013-08-25 10:18:25 +0200149 strncpy( cur->oid, oid, strlen( oid ) );
150 strncpy( cur->name, s, c - s );
151
152 s = c + 1;
153 in_tag = 1;
154 }
155 c++;
156 }
157
158exit:
159
160 return( ret );
161}
162
Paul Bakker1c0e5502013-08-26 13:41:01 +0200163int x509write_csr_set_extension( x509_csr *ctx,
164 const char *oid, size_t oid_len,
165 const unsigned char *val, size_t val_len )
Paul Bakkerfde42702013-08-25 14:47:27 +0200166{
Paul Bakkere5eae762013-08-26 12:05:14 +0200167 asn1_named_data *cur;
Paul Bakkere5eae762013-08-26 12:05:14 +0200168
Paul Bakker1c0e5502013-08-26 13:41:01 +0200169 if( ( cur = asn1_find_named_data( ctx->extensions, oid,
170 oid_len ) ) == NULL )
Paul Bakkere5eae762013-08-26 12:05:14 +0200171 {
172 cur = polarssl_malloc( sizeof(asn1_named_data) );
173 if( cur == NULL )
174 return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
175
176 memset( cur, 0, sizeof(asn1_named_data) );
177
Paul Bakker1c0e5502013-08-26 13:41:01 +0200178 cur->oid.len = oid_len;
179 cur->oid.p = polarssl_malloc( oid_len );
Paul Bakkere5eae762013-08-26 12:05:14 +0200180 if( cur->oid.p == NULL )
181 {
Paul Bakker1c0e5502013-08-26 13:41:01 +0200182 polarssl_free( cur );
Paul Bakkere5eae762013-08-26 12:05:14 +0200183 return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
184 }
185
Paul Bakker1c0e5502013-08-26 13:41:01 +0200186 cur->val.len = val_len;
187 cur->val.p = polarssl_malloc( val_len );
Paul Bakkere5eae762013-08-26 12:05:14 +0200188 if( cur->val.p == NULL )
189 {
Paul Bakker1c0e5502013-08-26 13:41:01 +0200190 polarssl_free( cur->oid.p );
191 polarssl_free( cur );
Paul Bakkere5eae762013-08-26 12:05:14 +0200192 return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
193 }
194
Paul Bakker1c0e5502013-08-26 13:41:01 +0200195 memcpy( cur->oid.p, oid, oid_len );
Paul Bakkere5eae762013-08-26 12:05:14 +0200196
197 cur->next = ctx->extensions;
198 ctx->extensions = cur;
199 }
200
Paul Bakker1c0e5502013-08-26 13:41:01 +0200201 if( cur->val.len != val_len )
202 {
203 polarssl_free( cur->val.p );
204
205 cur->val.len = val_len;
206 cur->val.p = polarssl_malloc( val_len );
207 if( cur->val.p == NULL )
208 {
209 polarssl_free( cur->oid.p );
210 polarssl_free( cur );
211 return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED );
212 }
213 }
214
215 memcpy( cur->val.p, val, val_len );
216
217 return( 0 );
218}
219
220int x509write_csr_set_key_usage( x509_csr *ctx, unsigned char key_usage )
221{
222 unsigned char buf[4];
223 unsigned char *c;
224 int ret;
225
226 c = buf + 4;
227
Paul Bakker624d03a2013-08-26 14:12:57 +0200228 if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
Paul Bakker1c0e5502013-08-26 13:41:01 +0200229 return( ret );
230
231 ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE,
232 OID_SIZE( OID_KEY_USAGE ),
233 buf, 4 );
234 if( ret != 0 )
235 return( ret );
236
237 return( 0 );
238}
239
240int x509write_csr_set_ns_cert_type( x509_csr *ctx, unsigned char ns_cert_type )
241{
242 unsigned char buf[4];
243 unsigned char *c;
244 int ret;
245
246 c = buf + 4;
247
248 if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
249 return( ret );
250
251 ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE,
252 OID_SIZE( OID_NS_CERT_TYPE ),
253 buf, 4 );
254 if( ret != 0 )
255 return( ret );
Paul Bakkere5eae762013-08-26 12:05:14 +0200256
257 return( 0 );
Paul Bakkerfde42702013-08-25 14:47:27 +0200258}
259
Paul Bakker82e29452013-08-25 11:01:31 +0200260int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000261{
262 int ret;
263 unsigned char *c;
264 size_t len = 0;
265
266 c = buf + size - 1;
267
Paul Bakker8eabfc12013-08-25 10:18:25 +0200268 /*
269 * RSAPublicKey ::= SEQUENCE {
270 * modulus INTEGER, -- n
271 * publicExponent INTEGER -- e
272 * }
273 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000274 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) );
275 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) );
276
277 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
278 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
279
280 if( c - buf < 1 )
281 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
282
Paul Bakker8eabfc12013-08-25 10:18:25 +0200283 /*
284 * SubjectPublicKeyInfo ::= SEQUENCE {
285 * algorithm AlgorithmIdentifier,
286 * subjectPublicKey BIT STRING }
287 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000288 *--c = 0;
289 len += 1;
290
291 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
292 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) );
293
294 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf, OID_PKCS1_RSA ) );
295
296 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
297 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
298
299 return( len );
300}
301
Paul Bakker82e29452013-08-25 11:01:31 +0200302int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000303{
304 int ret;
305 unsigned char *c;
306 size_t len = 0;
307
308 c = buf + size - 1;
309
310 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) );
311 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) );
312 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) );
313 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) );
314 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) );
315 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) );
316 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) );
317 ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) );
318 ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) );
319
320 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
321 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
322
323 // TODO: Make NON RSA Specific variant later on
324/* *--c = 0;
325 len += 1;
326
327 len += asn1_write_len( &c, len);
328 len += asn1_write_tag( &c, ASN1_BIT_STRING );
329
330 len += asn1_write_oid( &c, OID_PKCS1_RSA );
331
332 len += asn1_write_int( &c, 0 );
333
334 len += asn1_write_len( &c, len);
335 len += asn1_write_tag( &c, ASN1_CONSTRUCTED | ASN1_SEQUENCE );*/
336
337/* for(i = 0; i < len; ++i)
338 {
339 if (i % 16 == 0 ) printf("\n");
340 printf("%02x ", c[i]);
341 }
342 printf("\n");*/
343
344 return( len );
345}
346
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200347static int x509_write_name( unsigned char **p, unsigned char *start, char *oid,
348 char *name )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000349{
350 int ret;
351 size_t string_len = 0;
352 size_t oid_len = 0;
353 size_t len = 0;
354
Paul Bakker05888152012-02-16 10:26:57 +0000355 // Write PrintableString for all except OID_PKCS9_EMAIL
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000356 //
Paul Bakker05888152012-02-16 10:26:57 +0000357 if( OID_SIZE( OID_PKCS9_EMAIL ) == strlen( oid ) &&
358 memcmp( oid, OID_PKCS9_EMAIL, strlen( oid ) ) == 0 )
359 {
360 ASN1_CHK_ADD( string_len, asn1_write_ia5_string( p, start, name ) );
361 }
362 else
363 ASN1_CHK_ADD( string_len, asn1_write_printable_string( p, start, name ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000364
365 // Write OID
366 //
367 ASN1_CHK_ADD( oid_len, asn1_write_oid( p, start, oid ) );
368
369 len = oid_len + string_len;
370 ASN1_CHK_ADD( len, asn1_write_len( p, start, oid_len + string_len ) );
371 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
372
373 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
374 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) );
375
376 return( len );
377}
378
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200379static int x509_write_sig( unsigned char **p, unsigned char *start,
380 const char *oid, unsigned char *sig, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000381{
382 int ret;
383 size_t len = 0;
384
385 if( *p - start < (int) size + 1 )
386 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
387
388 len = size;
389 (*p) -= len;
390 memcpy( *p, sig, len );
391
392 *--(*p) = 0;
393 len += 1;
394
395 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
396 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
397
398 // Write OID
399 //
400 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid ) );
401
402 return( len );
403}
404
Paul Bakker82e29452013-08-25 11:01:31 +0200405int x509write_csr_der( x509_csr *ctx, unsigned char *buf, size_t size )
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000406{
407 int ret;
Paul Bakkerc70b9822013-04-07 22:00:46 +0200408 const char *sig_oid;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000409 unsigned char *c, *c2;
Paul Bakker3cac5e02012-02-16 14:08:06 +0000410 unsigned char hash[64];
411 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000412 unsigned char tmp_buf[2048];
Paul Bakkere5eae762013-08-26 12:05:14 +0200413 size_t sub_len = 0, pub_len = 0, sig_len = 0;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000414 size_t len = 0;
Paul Bakker8eabfc12013-08-25 10:18:25 +0200415 x509_req_name *cur = ctx->subject;
Paul Bakkere5eae762013-08-26 12:05:14 +0200416 asn1_named_data *cur_ext = ctx->extensions;
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000417
418 c = tmp_buf + 2048 - 1;
419
Paul Bakkere5eae762013-08-26 12:05:14 +0200420 while( cur_ext != NULL )
Paul Bakkerfde42702013-08-25 14:47:27 +0200421 {
Paul Bakkere5eae762013-08-26 12:05:14 +0200422 size_t ext_len = 0;
423
424 ASN1_CHK_ADD( ext_len, asn1_write_raw_buffer( &c, tmp_buf, cur_ext->val.p,
425 cur_ext->val.len ) );
426 ASN1_CHK_ADD( ext_len, asn1_write_len( &c, tmp_buf, cur_ext->val.len ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200427 ASN1_CHK_ADD( ext_len, asn1_write_tag( &c, tmp_buf, ASN1_OCTET_STRING ) );
Paul Bakkere5eae762013-08-26 12:05:14 +0200428
429 ASN1_CHK_ADD( ext_len, asn1_write_raw_buffer( &c, tmp_buf, cur_ext->oid.p,
430 cur_ext->oid.len ) );
431 ASN1_CHK_ADD( ext_len, asn1_write_len( &c, tmp_buf, cur_ext->oid.len ) );
432 ASN1_CHK_ADD( ext_len, asn1_write_tag( &c, tmp_buf, ASN1_OID ) );
433
Paul Bakkerfde42702013-08-25 14:47:27 +0200434 ASN1_CHK_ADD( ext_len, asn1_write_len( &c, tmp_buf, ext_len ) );
435 ASN1_CHK_ADD( ext_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkere5eae762013-08-26 12:05:14 +0200436
437 cur_ext = cur_ext->next;
438
439 len += ext_len;
Paul Bakkerfde42702013-08-25 14:47:27 +0200440 }
441
Paul Bakkere5eae762013-08-26 12:05:14 +0200442 if( len )
Paul Bakkerfde42702013-08-25 14:47:27 +0200443 {
Paul Bakkere5eae762013-08-26 12:05:14 +0200444 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
445 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200446
Paul Bakkere5eae762013-08-26 12:05:14 +0200447 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
448 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200449
Paul Bakkere5eae762013-08-26 12:05:14 +0200450 ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200451
Paul Bakkere5eae762013-08-26 12:05:14 +0200452 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
453 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerfde42702013-08-25 14:47:27 +0200454 }
455
Paul Bakkere5eae762013-08-26 12:05:14 +0200456 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000457 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) );
458
Paul Bakker8eabfc12013-08-25 10:18:25 +0200459 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->rsa->E ) );
460 ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->rsa->N ) );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000461
462 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
463 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
464
465 if( c - tmp_buf < 1 )
466 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
467
Paul Bakker8eabfc12013-08-25 10:18:25 +0200468 /*
469 * AlgorithmIdentifier ::= SEQUENCE {
470 * algorithm OBJECT IDENTIFIER,
471 * parameters ANY DEFINED BY algorithm OPTIONAL }
472 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000473 *--c = 0;
474 pub_len += 1;
475
476 ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
477 ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_BIT_STRING ) );
478
479 ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf, OID_PKCS1_RSA ) );
480
481 len += pub_len;
482 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) );
483 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
484
485 while( cur != NULL )
486 {
487 ASN1_CHK_ADD( sub_len, x509_write_name( &c, tmp_buf, cur->oid, cur->name ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200488
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000489 cur = cur->next;
490 }
491
492 len += sub_len;
493 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
494 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
495
Paul Bakker8eabfc12013-08-25 10:18:25 +0200496 /*
497 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
498 */
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000499 ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
500
501 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
502 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200503
Paul Bakker8eabfc12013-08-25 10:18:25 +0200504 md( md_info_from_type( ctx->md_alg ), c, len, hash );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000505
Paul Bakker8eabfc12013-08-25 10:18:25 +0200506 rsa_pkcs1_sign( ctx->rsa, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig );
Paul Bakker3cac5e02012-02-16 14:08:06 +0000507
508 // Generate correct OID
509 //
Paul Bakker8eabfc12013-08-25 10:18:25 +0200510 ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid );
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000511
512 c2 = buf + size - 1;
Paul Bakker8eabfc12013-08-25 10:18:25 +0200513 ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig, ctx->rsa->len ) );
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200514
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000515 c2 -= len;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200516 memcpy( c2, c, len );
517
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000518 len += sig_len;
519 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
520 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
521
522 return( len );
523}
524
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200525#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n"
526#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n"
527
528#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n"
529#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n"
530
531#define PEM_BEGIN_PRIVATE_KEY "-----BEGIN RSA PRIVATE KEY-----\n"
532#define PEM_END_PRIVATE_KEY "-----END RSA PRIVATE KEY-----\n"
Paul Bakker135f1e92013-08-26 16:54:13 +0200533
534#if defined(POLARSSL_BASE64_C)
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200535static int x509write_pemify( const char *begin_str, const char *end_str,
536 const unsigned char *der_data, size_t der_len,
537 unsigned char *buf, size_t size )
Paul Bakker135f1e92013-08-26 16:54:13 +0200538{
539 int ret;
Paul Bakker135f1e92013-08-26 16:54:13 +0200540 unsigned char base_buf[4096];
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200541 unsigned char *c = base_buf, *p = buf;
542 size_t len = 0, olen = sizeof(base_buf);
Paul Bakker135f1e92013-08-26 16:54:13 +0200543
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200544 if( ( ret = base64_encode( base_buf, &olen, der_data, der_len ) ) != 0 )
Paul Bakker135f1e92013-08-26 16:54:13 +0200545 return( ret );
546
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200547 if( olen + strlen( begin_str ) + strlen( end_str ) +
Paul Bakker135f1e92013-08-26 16:54:13 +0200548 olen / 64 > size )
549 {
550 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
551 }
552
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200553 memcpy( p, begin_str, strlen( begin_str ) );
554 p += strlen( begin_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200555
556 while( olen )
557 {
558 len = ( olen > 64 ) ? 64 : olen;
559 memcpy( p, c, len );
560 olen -= len;
561 p += len;
562 c += len;
563 *p++ = '\n';
564 }
565
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200566 memcpy( p, end_str, strlen( end_str ) );
567 p += strlen( end_str );
Paul Bakker135f1e92013-08-26 16:54:13 +0200568
569 *p = '\0';
570
571 return( 0 );
572}
Paul Bakkerf3df61a2013-08-26 17:22:23 +0200573
574int x509write_pubkey_pem( rsa_context *rsa, unsigned char *buf, size_t size )
575{
576 int ret;
577 unsigned char output_buf[4096];
578
579 if( ( ret = x509write_pubkey_der( rsa, output_buf,
580 sizeof(output_buf) ) ) < 0 )
581 {
582 return( ret );
583 }
584
585 if( ( ret = x509write_pemify( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
586 output_buf + sizeof(output_buf) - 1 - ret,
587 ret, buf, size ) ) != 0 )
588 {
589 return( ret );
590 }
591
592 return( 0 );
593}
594
595int x509write_key_pem( rsa_context *rsa, unsigned char *buf, size_t size )
596{
597 int ret;
598 unsigned char output_buf[4096];
599
600 if( ( ret = x509write_key_der( rsa, output_buf,
601 sizeof(output_buf) ) ) < 0 )
602 {
603 return( ret );
604 }
605
606 if( ( ret = x509write_pemify( PEM_BEGIN_PRIVATE_KEY, PEM_END_PRIVATE_KEY,
607 output_buf + sizeof(output_buf) - 1 - ret,
608 ret, buf, size ) ) != 0 )
609 {
610 return( ret );
611 }
612
613 return( 0 );
614}
615
616int x509write_csr_pem( x509_csr *ctx, unsigned char *buf, size_t size )
617{
618 int ret;
619 unsigned char output_buf[4096];
620
621 if( ( ret = x509write_csr_der( ctx, output_buf,
622 sizeof(output_buf) ) ) < 0 )
623 {
624 return( ret );
625 }
626
627 if( ( ret = x509write_pemify( PEM_BEGIN_CSR, PEM_END_CSR,
628 output_buf + sizeof(output_buf) - 1 - ret,
629 ret, buf, size ) ) != 0 )
630 {
631 return( ret );
632 }
633
634 return( 0 );
635}
Paul Bakker135f1e92013-08-26 16:54:13 +0200636#endif /* POLARSSL_BASE64_C */
637
Paul Bakkerbdb912d2012-02-13 23:11:30 +0000638#endif