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