PolarSSL v1.3.3
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) || defined(EFIX64) || defined(EFI32)
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 && !defined(EFIX64) && \
306  !defined(EFI32)
307 #include <stdarg.h>
308 
309 #if !defined vsnprintf
310 #define vsnprintf _vsnprintf
311 #endif // vsnprintf
312 
313 /*
314  * Windows _snprintf and _vsnprintf are not compatible to linux versions.
315  * Result value is not size of buffer needed, but -1 if no fit is possible.
316  *
317  * This fuction tries to 'fix' this by at least suggesting enlarging the
318  * size by 20.
319  */
320 static int compat_snprintf(char *str, size_t size, const char *format, ...)
321 {
322  va_list ap;
323  int res = -1;
324 
325  va_start( ap, format );
326 
327  res = vsnprintf( str, size, format, ap );
328 
329  va_end( ap );
330 
331  // No quick fix possible
332  if ( res < 0 )
333  return( (int) size + 20 );
334 
335  return res;
336 }
337 
338 #define snprintf compat_snprintf
339 #endif
340 
341 #define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2
342 
343 #define SAFE_SNPRINTF() \
344 { \
345  if( ret == -1 ) \
346  return( -1 ); \
347  \
348  if ( (unsigned int) ret > n ) { \
349  p[n - 1] = '\0'; \
350  return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
351  } \
352  \
353  n -= (unsigned int) ret; \
354  p += (unsigned int) ret; \
355 }
356 
357 #define BEFORE_COLON 14
358 #define BC "14"
359 /*
360  * Return an informational string about the CSR.
361  */
362 int x509_csr_info( char *buf, size_t size, const char *prefix,
363  const x509_csr *csr )
364 {
365  int ret;
366  size_t n;
367  char *p;
368  const char *desc;
369  char key_size_str[BEFORE_COLON];
370 
371  p = buf;
372  n = size;
373 
374  ret = snprintf( p, n, "%sCSR version : %d",
375  prefix, csr->version );
376  SAFE_SNPRINTF();
377 
378  ret = snprintf( p, n, "\n%ssubject name : ", prefix );
379  SAFE_SNPRINTF();
380  ret = x509_dn_gets( p, n, &csr->subject );
381  SAFE_SNPRINTF();
382 
383  ret = snprintf( p, n, "\n%ssigned using : ", prefix );
384  SAFE_SNPRINTF();
385 
386  ret = oid_get_sig_alg_desc( &csr->sig_oid, &desc );
387  if( ret != 0 )
388  ret = snprintf( p, n, "???" );
389  else
390  ret = snprintf( p, n, "%s", desc );
391  SAFE_SNPRINTF();
392 
393  if( ( ret = x509_key_size_helper( key_size_str, BEFORE_COLON,
394  pk_get_name( &csr->pk ) ) ) != 0 )
395  {
396  return( ret );
397  }
398 
399  ret = snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str,
400  (int) pk_get_size( &csr->pk ) );
401  SAFE_SNPRINTF();
402 
403  return( (int) ( size - n ) );
404 }
405 
406 /*
407  * Initialize a CSR
408  */
409 void x509_csr_init( x509_csr *csr )
410 {
411  memset( csr, 0, sizeof(x509_csr) );
412 }
413 
414 /*
415  * Unallocate all CSR data
416  */
417 void x509_csr_free( x509_csr *csr )
418 {
419  x509_name *name_cur;
420  x509_name *name_prv;
421 
422  if( csr == NULL )
423  return;
424 
425  pk_free( &csr->pk );
426 
427  name_cur = csr->subject.next;
428  while( name_cur != NULL )
429  {
430  name_prv = name_cur;
431  name_cur = name_cur->next;
432  memset( name_prv, 0, sizeof( x509_name ) );
433  polarssl_free( name_prv );
434  }
435 
436  if( csr->raw.p != NULL )
437  {
438  memset( csr->raw.p, 0, csr->raw.len );
439  polarssl_free( csr->raw.p );
440  }
441 
442  memset( csr, 0, sizeof( x509_csr ) );
443 }
444 
445 #endif /* POLARSSL_X509_CSR_PARSE_C */
Memory allocation layer.
void *(* polarssl_malloc)(size_t len)
int x509_get_name(unsigned char **p, const unsigned char *end, x509_name *cur)
#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH
Actual length differs from expected length.
Definition: asn1.h:53
size_t pk_get_size(const pk_context *ctx)
Get the size in bits of the underlying key.
#define POLARSSL_ERR_X509_INVALID_FORMAT
The CRT/CRL/CSR format is invalid, e.g.
Definition: x509.h:50
int x509_key_size_helper(char *buf, size_t size, const char *name)
int asn1_get_int(unsigned char **p, const unsigned char *end, int *val)
Retrieve an integer ASN.1 tag and its value.
int x509_get_alg_null(unsigned char **p, const unsigned char *end, x509_buf *alg)
#define ASN1_SEQUENCE
Definition: asn1.h:78
Configuration options (set of defines)
#define POLARSSL_ERR_X509_UNKNOWN_SIG_ALG
Signature algorithm (oid) is unsupported.
Definition: x509.h:59
#define ASN1_CONSTRUCTED
Definition: asn1.h:88
int x509_get_sig(unsigned char **p, const unsigned char *end, x509_buf *sig)
const char * pk_get_name(const pk_context *ctx)
Access the type name.
#define POLARSSL_ERR_X509_UNKNOWN_VERSION
CRT/CRL/CSR has an unsupported version number.
Definition: x509.h:58
x509_name subject
The parsed subject data (named information object).
Definition: x509_csr.h:58
Object Identifier (OID) database.
x509_buf cri
The raw CertificateRequestInfo body (DER).
Definition: x509_csr.h:53
x509_buf sig_oid
Definition: x509_csr.h:62
Privacy Enhanced Mail (PEM) decoding.
int x509_dn_gets(char *buf, size_t size, const x509_name *dn)
Store the certificate DN in printable form into buf; no more than size characters will be written...
void(* polarssl_free)(void *ptr)
x509_buf sig
Definition: x509_csr.h:63
unsigned char * p
ASN1 data, e.g.
Definition: asn1.h:120
int oid_get_sig_alg_desc(const asn1_buf *oid, const char **desc)
Translate SignatureAlgorithm OID into description.
X.509 certificate signing request parsing and writing.
void x509_csr_free(x509_csr *csr)
Unallocate all CSR data.
int x509_get_sig_alg(const x509_buf *sig_oid, md_type_t *md_alg, pk_type_t *pk_alg)
int pk_parse_subpubkey(unsigned char **p, const unsigned char *end, pk_context *pk)
Parse a SubjectPublicKeyInfo DER structure.
int x509_load_file(const char *path, unsigned char **buf, size_t *n)
#define ASN1_CONTEXT_SPECIFIC
Definition: asn1.h:89
pk_type_t sig_pk
&lt; Internal representation of the Public Key algorithm of the signature algorithm, e...
Definition: x509_csr.h:65
pk_context pk
Container for the public key context.
Definition: x509_csr.h:60
int x509_csr_parse(x509_csr *csr, const unsigned char *buf, size_t buflen)
Load a Certificate Signing Request (CSR)
Container for a sequence or list of &#39;named&#39; ASN.1 data items.
Definition: asn1.h:148
size_t len
ASN1 length, e.g.
Definition: asn1.h:119
x509_buf raw
The raw CSR data (DER).
Definition: x509_csr.h:52
void pk_free(pk_context *ctx)
Free a pk_context.
int asn1_get_tag(unsigned char **p, const unsigned char *end, size_t *len, int tag)
Get the tag and length of the tag.
#define POLARSSL_ERR_X509_INVALID_VERSION
The CRT/CRL/CSR version element is invalid.
Definition: x509.h:51
int x509_csr_info(char *buf, size_t size, const char *prefix, const x509_csr *csr)
Returns an informational string about the CSR.
int version
Definition: x509_csr.h:55
struct _asn1_named_data * next
The next entry in the sequence.
Definition: asn1.h:152
Certificate Signing Request (CSR) structure.
Definition: x509_csr.h:50
#define POLARSSL_ERR_X509_BAD_INPUT_DATA
Input invalid.
Definition: x509.h:63
int x509_csr_parse_file(x509_csr *csr, const char *path)
Load a Certificate Signing Request (CSR)
#define POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT
No PEM header or footer found.
Definition: pem.h:38
md_type_t sig_md
Internal representation of the MD algorithm of the signature algorithm, e.g.
Definition: x509_csr.h:64
#define POLARSSL_ERR_X509_MALLOC_FAILED
Allocation of memory failed.
Definition: x509.h:64
void x509_csr_init(x509_csr *csr)
Initialize a CSR.
#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG
ASN1 tag was of an unexpected value.
Definition: asn1.h:51
x509_buf subject_raw
The raw subject data (DER).
Definition: x509_csr.h:57