PolarSSL v1.3.4
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, steal PEM buffer
116  */
117  p = pem.buf;
118  pem.buf = NULL;
119  len = pem.buflen;
120  pem_free( &pem );
121  }
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 )
137 
138  memcpy( p, buf, buflen );
139  }
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 );
157  }
158 
159  if( len != (size_t) ( end - p ) )
160  {
161  x509_csr_free( csr );
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 );
175  return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
176  }
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 );
196  }
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 );
207  return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
208  }
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  */
221  if( ( ret = pk_parse_subpubkey( &p, end, &csr->pk ) ) != 0 )
222  {
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,
232  {
233  x509_csr_free( csr );
234  return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
235  }
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 );
257  }
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 );
270  }
271 
272  return( 0 );
273 }
274 
275 #if defined(POLARSSL_FS_IO)
276 /*
277  * Load a CSR into the structure
278  */
279 int x509_csr_parse_file( x509_csr *csr, const char *path )
280 {
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 
288  ret = x509_csr_parse( csr, buf, n );
289 
290  memset( buf, 0, n + 1 );
291  polarssl_free( buf );
292 
293  return( ret );
294 }
295 #endif /* POLARSSL_FS_IO */
296 
297 #if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \
298  !defined(EFI32)
299 #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  */
312 static 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  */
354 int x509_csr_info( char *buf, size_t size, const char *prefix,
355  const x509_csr *csr )
356 {
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();
372  ret = x509_dn_gets( p, n, &csr->subject );
373  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 /*
399  * Initialize a CSR
400  */
401 void x509_csr_init( x509_csr *csr )
402 {
403  memset( csr, 0, sizeof(x509_csr) );
404 }
405 
406 /*
407  * Unallocate all CSR data
408  */
409 void 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 */
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