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