blob: e45935a53f53fd78383a8b7191f4515e77883372 [file] [log] [blame]
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001/*
2 * X.509 Certificate Signing Request (CSR) parsing
3 *
4 * Copyright (C) 2006-2013, Brainspark B.V.
5 *
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 * The ITU-T X.509 standard defines a certificate format for PKI.
27 *
28 * http://www.ietf.org/rfc/rfc3279.txt
29 * http://www.ietf.org/rfc/rfc3280.txt
30 *
31 * ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
32 *
33 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
34 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
35 */
36
37#include "polarssl/config.h"
38
39#if defined(POLARSSL_X509_CSR_PARSE_C)
40
41#include "polarssl/x509_csr.h"
42#include "polarssl/oid.h"
43#if defined(POLARSSL_PEM_PARSE_C)
44#include "polarssl/pem.h"
45#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +020046
47#if defined(POLARSSL_MEMORY_C)
48#include "polarssl/memory.h"
49#else
50#define polarssl_malloc malloc
51#define polarssl_free free
52#endif
53
54#include <string.h>
55#include <stdlib.h>
56
Paul Bakkerfa6a6202013-10-28 18:48:30 +010057#if defined(POLARSSL_FS_IO) || defined(EFIX64) || defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020058#include <stdio.h>
59#endif
60
61/*
62 * Version ::= INTEGER { v1(0) }
63 */
64static int x509_csr_get_version( unsigned char **p,
65 const unsigned char *end,
66 int *ver )
67{
68 int ret;
69
70 if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
71 {
72 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
73 {
74 *ver = 0;
75 return( 0 );
76 }
77
Paul Bakker51876562013-09-17 14:36:05 +020078 return( POLARSSL_ERR_X509_INVALID_VERSION + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +020079 }
80
81 return( 0 );
82}
83
84/*
85 * Parse a CSR
86 */
Paul Bakkerddf26b42013-09-18 13:46:23 +020087int x509_csr_parse( x509_csr *csr, const unsigned char *buf, size_t buflen )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020088{
89 int ret;
90 size_t len;
91 unsigned char *p, *end;
92#if defined(POLARSSL_PEM_PARSE_C)
93 size_t use_len;
94 pem_context pem;
95#endif
96
97 /*
98 * Check for valid input
99 */
100 if( csr == NULL || buf == NULL )
Paul Bakker51876562013-09-17 14:36:05 +0200101 return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200102
Paul Bakker369d2eb2013-09-18 11:58:25 +0200103 x509_csr_init( csr );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200104
105#if defined(POLARSSL_PEM_PARSE_C)
106 pem_init( &pem );
107 ret = pem_read_buffer( &pem,
108 "-----BEGIN CERTIFICATE REQUEST-----",
109 "-----END CERTIFICATE REQUEST-----",
110 buf, NULL, 0, &use_len );
111
112 if( ret == 0 )
113 {
114 /*
Manuel Pégourié-Gonnard7c593632014-01-20 10:27:13 +0100115 * Was PEM encoded, steal PEM buffer
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200116 */
117 p = pem.buf;
118 pem.buf = NULL;
119 len = pem.buflen;
120 pem_free( &pem );
121 }
122 else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
123 {
124 pem_free( &pem );
125 return( ret );
126 }
127 else
128#endif
129 {
130 /*
131 * nope, copy the raw DER data
132 */
133 p = (unsigned char *) polarssl_malloc( len = buflen );
134
135 if( p == NULL )
136 return( POLARSSL_ERR_X509_MALLOC_FAILED );
137
138 memcpy( p, buf, buflen );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200139 }
140
141 csr->raw.p = p;
142 csr->raw.len = len;
143 end = p + len;
144
145 /*
146 * CertificationRequest ::= SEQUENCE {
147 * certificationRequestInfo CertificationRequestInfo,
148 * signatureAlgorithm AlgorithmIdentifier,
149 * signature BIT STRING
150 * }
151 */
152 if( ( ret = asn1_get_tag( &p, end, &len,
153 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
154 {
155 x509_csr_free( csr );
Paul Bakker51876562013-09-17 14:36:05 +0200156 return( POLARSSL_ERR_X509_INVALID_FORMAT );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200157 }
158
159 if( len != (size_t) ( end - p ) )
160 {
161 x509_csr_free( csr );
Paul Bakker51876562013-09-17 14:36:05 +0200162 return( POLARSSL_ERR_X509_INVALID_FORMAT +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200163 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
164 }
165
166 /*
167 * CertificationRequestInfo ::= SEQUENCE {
168 */
169 csr->cri.p = p;
170
171 if( ( ret = asn1_get_tag( &p, end, &len,
172 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
173 {
174 x509_csr_free( csr );
Paul Bakker51876562013-09-17 14:36:05 +0200175 return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200176 }
177
178 end = p + len;
179 csr->cri.len = end - csr->cri.p;
180
181 /*
182 * Version ::= INTEGER { v1(0) }
183 */
184 if( ( ret = x509_csr_get_version( &p, end, &csr->version ) ) != 0 )
185 {
186 x509_csr_free( csr );
187 return( ret );
188 }
189
190 csr->version++;
191
192 if( csr->version != 1 )
193 {
194 x509_csr_free( csr );
Paul Bakker51876562013-09-17 14:36:05 +0200195 return( POLARSSL_ERR_X509_UNKNOWN_VERSION );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200196 }
197
198 /*
199 * subject Name
200 */
201 csr->subject_raw.p = p;
202
203 if( ( ret = asn1_get_tag( &p, end, &len,
204 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
205 {
206 x509_csr_free( csr );
Paul Bakker51876562013-09-17 14:36:05 +0200207 return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200208 }
209
210 if( ( ret = x509_get_name( &p, p + len, &csr->subject ) ) != 0 )
211 {
212 x509_csr_free( csr );
213 return( ret );
214 }
215
216 csr->subject_raw.len = p - csr->subject_raw.p;
217
218 /*
219 * subjectPKInfo SubjectPublicKeyInfo
220 */
Paul Bakkerda771152013-09-16 22:45:03 +0200221 if( ( ret = pk_parse_subpubkey( &p, end, &csr->pk ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200222 {
223 x509_csr_free( csr );
224 return( ret );
225 }
226
227 /*
228 * attributes [0] Attributes
229 */
230 if( ( ret = asn1_get_tag( &p, end, &len,
231 ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) ) != 0 )
232 {
233 x509_csr_free( csr );
Paul Bakker51876562013-09-17 14:36:05 +0200234 return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200235 }
236 // TODO Parse Attributes / extension requests
237
238 p += len;
239
240 end = csr->raw.p + csr->raw.len;
241
242 /*
243 * signatureAlgorithm AlgorithmIdentifier,
244 * signature BIT STRING
245 */
246 if( ( ret = x509_get_alg_null( &p, end, &csr->sig_oid ) ) != 0 )
247 {
248 x509_csr_free( csr );
249 return( ret );
250 }
251
252 if( ( ret = x509_get_sig_alg( &csr->sig_oid, &csr->sig_md,
253 &csr->sig_pk ) ) != 0 )
254 {
255 x509_csr_free( csr );
Paul Bakker51876562013-09-17 14:36:05 +0200256 return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200257 }
258
259 if( ( ret = x509_get_sig( &p, end, &csr->sig ) ) != 0 )
260 {
261 x509_csr_free( csr );
262 return( ret );
263 }
264
265 if( p != end )
266 {
267 x509_csr_free( csr );
Paul Bakker51876562013-09-17 14:36:05 +0200268 return( POLARSSL_ERR_X509_INVALID_FORMAT +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200269 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
270 }
271
272 return( 0 );
273}
274
275#if defined(POLARSSL_FS_IO)
276/*
277 * Load a CSR into the structure
278 */
Paul Bakkerddf26b42013-09-18 13:46:23 +0200279int x509_csr_parse_file( x509_csr *csr, const char *path )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200280{
281 int ret;
282 size_t n;
283 unsigned char *buf;
284
285 if ( ( ret = x509_load_file( path, &buf, &n ) ) != 0 )
286 return( ret );
287
Paul Bakkerddf26b42013-09-18 13:46:23 +0200288 ret = x509_csr_parse( csr, buf, n );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200289
290 memset( buf, 0, n + 1 );
291 polarssl_free( buf );
292
293 return( ret );
294}
295#endif /* POLARSSL_FS_IO */
296
Paul Bakker6edcd412013-10-29 15:22:54 +0100297#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \
298 !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200299#include <stdarg.h>
300
301#if !defined vsnprintf
302#define vsnprintf _vsnprintf
303#endif // vsnprintf
304
305/*
306 * Windows _snprintf and _vsnprintf are not compatible to linux versions.
307 * Result value is not size of buffer needed, but -1 if no fit is possible.
308 *
309 * This fuction tries to 'fix' this by at least suggesting enlarging the
310 * size by 20.
311 */
312static int compat_snprintf(char *str, size_t size, const char *format, ...)
313{
314 va_list ap;
315 int res = -1;
316
317 va_start( ap, format );
318
319 res = vsnprintf( str, size, format, ap );
320
321 va_end( ap );
322
323 // No quick fix possible
324 if ( res < 0 )
325 return( (int) size + 20 );
326
327 return res;
328}
329
330#define snprintf compat_snprintf
331#endif
332
333#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2
334
335#define SAFE_SNPRINTF() \
336{ \
337 if( ret == -1 ) \
338 return( -1 ); \
339 \
340 if ( (unsigned int) ret > n ) { \
341 p[n - 1] = '\0'; \
342 return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
343 } \
344 \
345 n -= (unsigned int) ret; \
346 p += (unsigned int) ret; \
347}
348
349#define BEFORE_COLON 14
350#define BC "14"
351/*
352 * Return an informational string about the CSR.
353 */
Paul Bakkerddf26b42013-09-18 13:46:23 +0200354int x509_csr_info( char *buf, size_t size, const char *prefix,
355 const x509_csr *csr )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200356{
357 int ret;
358 size_t n;
359 char *p;
360 const char *desc;
361 char key_size_str[BEFORE_COLON];
362
363 p = buf;
364 n = size;
365
366 ret = snprintf( p, n, "%sCSR version : %d",
367 prefix, csr->version );
368 SAFE_SNPRINTF();
369
370 ret = snprintf( p, n, "\n%ssubject name : ", prefix );
371 SAFE_SNPRINTF();
Paul Bakker86d0c192013-09-18 11:11:02 +0200372 ret = x509_dn_gets( p, n, &csr->subject );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200373 SAFE_SNPRINTF();
374
375 ret = snprintf( p, n, "\n%ssigned using : ", prefix );
376 SAFE_SNPRINTF();
377
378 ret = oid_get_sig_alg_desc( &csr->sig_oid, &desc );
379 if( ret != 0 )
380 ret = snprintf( p, n, "???" );
381 else
382 ret = snprintf( p, n, "%s", desc );
383 SAFE_SNPRINTF();
384
385 if( ( ret = x509_key_size_helper( key_size_str, BEFORE_COLON,
386 pk_get_name( &csr->pk ) ) ) != 0 )
387 {
388 return( ret );
389 }
390
391 ret = snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str,
392 (int) pk_get_size( &csr->pk ) );
393 SAFE_SNPRINTF();
394
395 return( (int) ( size - n ) );
396}
397
398/*
Paul Bakker369d2eb2013-09-18 11:58:25 +0200399 * Initialize a CSR
400 */
401void x509_csr_init( x509_csr *csr )
402{
403 memset( csr, 0, sizeof(x509_csr) );
404}
405
406/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200407 * Unallocate all CSR data
408 */
409void x509_csr_free( x509_csr *csr )
410{
411 x509_name *name_cur;
412 x509_name *name_prv;
413
414 if( csr == NULL )
415 return;
416
417 pk_free( &csr->pk );
418
419 name_cur = csr->subject.next;
420 while( name_cur != NULL )
421 {
422 name_prv = name_cur;
423 name_cur = name_cur->next;
424 memset( name_prv, 0, sizeof( x509_name ) );
425 polarssl_free( name_prv );
426 }
427
428 if( csr->raw.p != NULL )
429 {
430 memset( csr->raw.p, 0, csr->raw.len );
431 polarssl_free( csr->raw.p );
432 }
433
434 memset( csr, 0, sizeof( x509_csr ) );
435}
436
437#endif /* POLARSSL_X509_CSR_PARSE_C */