blob: e4b05174c72b5336962d28182561783d8e635da0 [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
46#if defined(POLARSSL_ASN1_WRITE_C)
47#include "polarssl/asn1write.h"
48#endif
49
50#if defined(POLARSSL_MEMORY_C)
51#include "polarssl/memory.h"
52#else
53#define polarssl_malloc malloc
54#define polarssl_free free
55#endif
56
57#include <string.h>
58#include <stdlib.h>
59
60#if defined(POLARSSL_FS_IO)
61#include <stdio.h>
62#endif
63
64/*
65 * Version ::= INTEGER { v1(0) }
66 */
67static int x509_csr_get_version( unsigned char **p,
68 const unsigned char *end,
69 int *ver )
70{
71 int ret;
72
73 if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
74 {
75 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
76 {
77 *ver = 0;
78 return( 0 );
79 }
80
81 return( POLARSSL_ERR_X509_CERT_INVALID_VERSION + ret );
82 }
83
84 return( 0 );
85}
86
87/*
88 * Parse a CSR
89 */
90int x509parse_csr( x509_csr *csr, const unsigned char *buf, size_t buflen )
91{
92 int ret;
93 size_t len;
94 unsigned char *p, *end;
95#if defined(POLARSSL_PEM_PARSE_C)
96 size_t use_len;
97 pem_context pem;
98#endif
99
100 /*
101 * Check for valid input
102 */
103 if( csr == NULL || buf == NULL )
104 return( POLARSSL_ERR_X509_INVALID_INPUT );
105
106 memset( csr, 0, sizeof( x509_csr ) );
107
108#if defined(POLARSSL_PEM_PARSE_C)
109 pem_init( &pem );
110 ret = pem_read_buffer( &pem,
111 "-----BEGIN CERTIFICATE REQUEST-----",
112 "-----END CERTIFICATE REQUEST-----",
113 buf, NULL, 0, &use_len );
114
115 if( ret == 0 )
116 {
117 /*
118 * Was PEM encoded
119 */
120 buflen -= use_len;
121 buf += use_len;
122
123 /*
124 * Steal PEM buffer
125 */
126 p = pem.buf;
127 pem.buf = NULL;
128 len = pem.buflen;
129 pem_free( &pem );
130 }
131 else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
132 {
133 pem_free( &pem );
134 return( ret );
135 }
136 else
137#endif
138 {
139 /*
140 * nope, copy the raw DER data
141 */
142 p = (unsigned char *) polarssl_malloc( len = buflen );
143
144 if( p == NULL )
145 return( POLARSSL_ERR_X509_MALLOC_FAILED );
146
147 memcpy( p, buf, buflen );
148
149 buflen = 0;
150 }
151
152 csr->raw.p = p;
153 csr->raw.len = len;
154 end = p + len;
155
156 /*
157 * CertificationRequest ::= SEQUENCE {
158 * certificationRequestInfo CertificationRequestInfo,
159 * signatureAlgorithm AlgorithmIdentifier,
160 * signature BIT STRING
161 * }
162 */
163 if( ( ret = asn1_get_tag( &p, end, &len,
164 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
165 {
166 x509_csr_free( csr );
167 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT );
168 }
169
170 if( len != (size_t) ( end - p ) )
171 {
172 x509_csr_free( csr );
173 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
174 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
175 }
176
177 /*
178 * CertificationRequestInfo ::= SEQUENCE {
179 */
180 csr->cri.p = p;
181
182 if( ( ret = asn1_get_tag( &p, end, &len,
183 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
184 {
185 x509_csr_free( csr );
186 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
187 }
188
189 end = p + len;
190 csr->cri.len = end - csr->cri.p;
191
192 /*
193 * Version ::= INTEGER { v1(0) }
194 */
195 if( ( ret = x509_csr_get_version( &p, end, &csr->version ) ) != 0 )
196 {
197 x509_csr_free( csr );
198 return( ret );
199 }
200
201 csr->version++;
202
203 if( csr->version != 1 )
204 {
205 x509_csr_free( csr );
206 return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION );
207 }
208
209 /*
210 * subject Name
211 */
212 csr->subject_raw.p = p;
213
214 if( ( ret = asn1_get_tag( &p, end, &len,
215 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
216 {
217 x509_csr_free( csr );
218 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
219 }
220
221 if( ( ret = x509_get_name( &p, p + len, &csr->subject ) ) != 0 )
222 {
223 x509_csr_free( csr );
224 return( ret );
225 }
226
227 csr->subject_raw.len = p - csr->subject_raw.p;
228
229 /*
230 * subjectPKInfo SubjectPublicKeyInfo
231 */
232 if( ( ret = pk_parse_get_pubkey( &p, end, &csr->pk ) ) != 0 )
233 {
234 x509_csr_free( csr );
235 return( ret );
236 }
237
238 /*
239 * attributes [0] Attributes
240 */
241 if( ( ret = asn1_get_tag( &p, end, &len,
242 ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) ) != 0 )
243 {
244 x509_csr_free( csr );
245 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
246 }
247 // TODO Parse Attributes / extension requests
248
249 p += len;
250
251 end = csr->raw.p + csr->raw.len;
252
253 /*
254 * signatureAlgorithm AlgorithmIdentifier,
255 * signature BIT STRING
256 */
257 if( ( ret = x509_get_alg_null( &p, end, &csr->sig_oid ) ) != 0 )
258 {
259 x509_csr_free( csr );
260 return( ret );
261 }
262
263 if( ( ret = x509_get_sig_alg( &csr->sig_oid, &csr->sig_md,
264 &csr->sig_pk ) ) != 0 )
265 {
266 x509_csr_free( csr );
267 return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
268 }
269
270 if( ( ret = x509_get_sig( &p, end, &csr->sig ) ) != 0 )
271 {
272 x509_csr_free( csr );
273 return( ret );
274 }
275
276 if( p != end )
277 {
278 x509_csr_free( csr );
279 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
280 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
281 }
282
283 return( 0 );
284}
285
286#if defined(POLARSSL_FS_IO)
287/*
288 * Load a CSR into the structure
289 */
290int x509parse_csrfile( x509_csr *csr, const char *path )
291{
292 int ret;
293 size_t n;
294 unsigned char *buf;
295
296 if ( ( ret = x509_load_file( path, &buf, &n ) ) != 0 )
297 return( ret );
298
299 ret = x509parse_csr( csr, buf, n );
300
301 memset( buf, 0, n + 1 );
302 polarssl_free( buf );
303
304 return( ret );
305}
306#endif /* POLARSSL_FS_IO */
307
308#if defined _MSC_VER && !defined snprintf
309#include <stdarg.h>
310
311#if !defined vsnprintf
312#define vsnprintf _vsnprintf
313#endif // vsnprintf
314
315/*
316 * Windows _snprintf and _vsnprintf are not compatible to linux versions.
317 * Result value is not size of buffer needed, but -1 if no fit is possible.
318 *
319 * This fuction tries to 'fix' this by at least suggesting enlarging the
320 * size by 20.
321 */
322static int compat_snprintf(char *str, size_t size, const char *format, ...)
323{
324 va_list ap;
325 int res = -1;
326
327 va_start( ap, format );
328
329 res = vsnprintf( str, size, format, ap );
330
331 va_end( ap );
332
333 // No quick fix possible
334 if ( res < 0 )
335 return( (int) size + 20 );
336
337 return res;
338}
339
340#define snprintf compat_snprintf
341#endif
342
343#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2
344
345#define SAFE_SNPRINTF() \
346{ \
347 if( ret == -1 ) \
348 return( -1 ); \
349 \
350 if ( (unsigned int) ret > n ) { \
351 p[n - 1] = '\0'; \
352 return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
353 } \
354 \
355 n -= (unsigned int) ret; \
356 p += (unsigned int) ret; \
357}
358
359#define BEFORE_COLON 14
360#define BC "14"
361/*
362 * Return an informational string about the CSR.
363 */
364int x509parse_csr_info( char *buf, size_t size, const char *prefix,
365 const x509_csr *csr )
366{
367 int ret;
368 size_t n;
369 char *p;
370 const char *desc;
371 char key_size_str[BEFORE_COLON];
372
373 p = buf;
374 n = size;
375
376 ret = snprintf( p, n, "%sCSR version : %d",
377 prefix, csr->version );
378 SAFE_SNPRINTF();
379
380 ret = snprintf( p, n, "\n%ssubject name : ", prefix );
381 SAFE_SNPRINTF();
382 ret = x509parse_dn_gets( p, n, &csr->subject );
383 SAFE_SNPRINTF();
384
385 ret = snprintf( p, n, "\n%ssigned using : ", prefix );
386 SAFE_SNPRINTF();
387
388 ret = oid_get_sig_alg_desc( &csr->sig_oid, &desc );
389 if( ret != 0 )
390 ret = snprintf( p, n, "???" );
391 else
392 ret = snprintf( p, n, "%s", desc );
393 SAFE_SNPRINTF();
394
395 if( ( ret = x509_key_size_helper( key_size_str, BEFORE_COLON,
396 pk_get_name( &csr->pk ) ) ) != 0 )
397 {
398 return( ret );
399 }
400
401 ret = snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str,
402 (int) pk_get_size( &csr->pk ) );
403 SAFE_SNPRINTF();
404
405 return( (int) ( size - n ) );
406}
407
408/*
409 * Unallocate all CSR data
410 */
411void x509_csr_free( x509_csr *csr )
412{
413 x509_name *name_cur;
414 x509_name *name_prv;
415
416 if( csr == NULL )
417 return;
418
419 pk_free( &csr->pk );
420
421 name_cur = csr->subject.next;
422 while( name_cur != NULL )
423 {
424 name_prv = name_cur;
425 name_cur = name_cur->next;
426 memset( name_prv, 0, sizeof( x509_name ) );
427 polarssl_free( name_prv );
428 }
429
430 if( csr->raw.p != NULL )
431 {
432 memset( csr->raw.p, 0, csr->raw.len );
433 polarssl_free( csr->raw.p );
434 }
435
436 memset( csr, 0, sizeof( x509_csr ) );
437}
438
439#endif /* POLARSSL_X509_CSR_PARSE_C */