blob: fdf2a7246eeccd56c474847ee01f5cdf8dace278 [file] [log] [blame]
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001/*
2 * X.509 base functions for creating certificates / CSRs
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#include "polarssl/config.h"
27
28#if defined(POLARSSL_X509_CREATE_C)
29
30#include "polarssl/x509.h"
31#include "polarssl/asn1write.h"
32#include "polarssl/oid.h"
33
Paul Bakker6edcd412013-10-29 15:22:54 +010034#if defined(_MSC_VER) && !defined strncasecmp && !defined(EFIX64) && \
35 !defined(EFI32)
Paul Bakker7b0be682013-10-29 14:24:37 +010036#define strncasecmp _strnicmp
37#endif
38
Paul Bakker50dc8502013-10-28 21:19:10 +010039int x509_string_to_names( asn1_named_data **head, const char *name )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020040{
41 int ret = 0;
Paul Bakker50dc8502013-10-28 21:19:10 +010042 const char *s = name, *c = s;
43 const char *end = s + strlen( s );
Paul Bakkerfcc17212013-10-11 09:36:52 +020044 const char *oid = NULL;
Paul Bakker7c6b2c32013-09-16 13:49:26 +020045 int in_tag = 1;
46 asn1_named_data *cur;
47
48 /* Clear existing chain if present */
49 asn1_free_named_data_list( head );
50
51 while( c <= end )
52 {
53 if( in_tag && *c == '=' )
54 {
Paul Bakker7b0be682013-10-29 14:24:37 +010055 if( c - s == 2 && strncasecmp( s, "CN", 2 ) == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020056 oid = OID_AT_CN;
Paul Bakker7b0be682013-10-29 14:24:37 +010057 else if( c - s == 1 && strncasecmp( s, "C", 1 ) == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020058 oid = OID_AT_COUNTRY;
Paul Bakker7b0be682013-10-29 14:24:37 +010059 else if( c - s == 1 && strncasecmp( s, "O", 1 ) == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020060 oid = OID_AT_ORGANIZATION;
Paul Bakker7b0be682013-10-29 14:24:37 +010061 else if( c - s == 1 && strncasecmp( s, "L", 1 ) == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020062 oid = OID_AT_LOCALITY;
Paul Bakker7b0be682013-10-29 14:24:37 +010063 else if( c - s == 1 && strncasecmp( s, "R", 1 ) == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020064 oid = OID_PKCS9_EMAIL;
Paul Bakker7b0be682013-10-29 14:24:37 +010065 else if( c - s == 2 && strncasecmp( s, "OU", 2 ) == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020066 oid = OID_AT_ORG_UNIT;
Paul Bakker7b0be682013-10-29 14:24:37 +010067 else if( c - s == 2 && strncasecmp( s, "ST", 2 ) == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020068 oid = OID_AT_STATE;
Paul Bakker7b0be682013-10-29 14:24:37 +010069 else if( c - s == 12 && strncasecmp( s, "serialNumber", 12 ) == 0 )
70 oid = OID_AT_SERIAL_NUMBER;
71 else if( c - s == 13 && strncasecmp( s, "postalAddress", 13 ) == 0 )
72 oid = OID_AT_POSTAL_ADDRESS;
73 else if( c - s == 10 && strncasecmp( s, "postalCode", 10 ) == 0 )
74 oid = OID_AT_POSTAL_CODE;
Paul Bakker7c6b2c32013-09-16 13:49:26 +020075 else
76 {
Paul Bakker51876562013-09-17 14:36:05 +020077 ret = POLARSSL_ERR_X509_UNKNOWN_OID;
Paul Bakker7c6b2c32013-09-16 13:49:26 +020078 goto exit;
79 }
80
81 s = c + 1;
82 in_tag = 0;
83 }
84
85 if( !in_tag && ( *c == ',' || c == end ) )
86 {
87 if( ( cur = asn1_store_named_data( head, oid, strlen( oid ),
88 (unsigned char *) s,
89 c - s ) ) == NULL )
90 {
Paul Bakker51876562013-09-17 14:36:05 +020091 return( POLARSSL_ERR_X509_MALLOC_FAILED );
Paul Bakker7c6b2c32013-09-16 13:49:26 +020092 }
93
94 while( c < end && *(c + 1) == ' ' )
95 c++;
96
97 s = c + 1;
98 in_tag = 1;
99 }
100 c++;
101 }
102
103exit:
104
105 return( ret );
106}
107
108/* The first byte of the value in the asn1_named_data structure is reserved
109 * to store the critical boolean for us
110 */
111int x509_set_extension( asn1_named_data **head, const char *oid, size_t oid_len,
112 int critical, const unsigned char *val, size_t val_len )
113{
114 asn1_named_data *cur;
115
116 if( ( cur = asn1_store_named_data( head, oid, oid_len,
117 NULL, val_len + 1 ) ) == NULL )
118 {
Paul Bakker51876562013-09-17 14:36:05 +0200119 return( POLARSSL_ERR_X509_MALLOC_FAILED );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200120 }
121
122 cur->val.p[0] = critical;
123 memcpy( cur->val.p + 1, val, val_len );
124
125 return( 0 );
126}
127
128/*
129 * RelativeDistinguishedName ::=
130 * SET OF AttributeTypeAndValue
131 *
132 * AttributeTypeAndValue ::= SEQUENCE {
133 * type AttributeType,
134 * value AttributeValue }
135 *
136 * AttributeType ::= OBJECT IDENTIFIER
137 *
138 * AttributeValue ::= ANY DEFINED BY AttributeType
139 */
140static int x509_write_name( unsigned char **p, unsigned char *start,
141 const char *oid, size_t oid_len,
142 const unsigned char *name, size_t name_len )
143{
144 int ret;
145 size_t len = 0;
146
147 // Write PrintableString for all except OID_PKCS9_EMAIL
148 //
149 if( OID_SIZE( OID_PKCS9_EMAIL ) == oid_len &&
150 memcmp( oid, OID_PKCS9_EMAIL, oid_len ) == 0 )
151 {
152 ASN1_CHK_ADD( len, asn1_write_ia5_string( p, start,
153 (const char *) name,
154 name_len ) );
155 }
156 else
157 {
158 ASN1_CHK_ADD( len, asn1_write_printable_string( p, start,
159 (const char *) name,
160 name_len ) );
161 }
162
163 // Write OID
164 //
165 ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
166
167 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
168 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
169
170 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
171 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) );
172
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200173 return( (int) len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200174}
175
176int x509_write_names( unsigned char **p, unsigned char *start,
177 asn1_named_data *first )
178{
179 int ret;
180 size_t len = 0;
181 asn1_named_data *cur = first;
182
183 while( cur != NULL )
184 {
185 ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p,
186 cur->oid.len,
187 cur->val.p, cur->val.len ) );
188 cur = cur->next;
189 }
190
191 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
192 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
193
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200194 return( (int) len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200195}
196
197int x509_write_sig( unsigned char **p, unsigned char *start,
198 const char *oid, size_t oid_len,
199 unsigned char *sig, size_t size )
200{
201 int ret;
202 size_t len = 0;
203
204 if( *p - start < (int) size + 1 )
205 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
206
207 len = size;
208 (*p) -= len;
209 memcpy( *p, sig, len );
210
211 *--(*p) = 0;
212 len += 1;
213
214 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
215 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
216
217 // Write OID
218 //
219 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid,
220 oid_len, 0 ) );
221
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200222 return( (int) len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200223}
224
225static int x509_write_extension( unsigned char **p, unsigned char *start,
226 asn1_named_data *ext )
227{
228 int ret;
229 size_t len = 0;
230
231 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->val.p + 1,
232 ext->val.len - 1 ) );
233 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->val.len - 1 ) );
234 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) );
235
236 if( ext->val.p[0] != 0 )
237 {
238 ASN1_CHK_ADD( len, asn1_write_bool( p, start, 1 ) );
239 }
240
241 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->oid.p,
242 ext->oid.len ) );
243 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->oid.len ) );
244 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) );
245
246 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
247 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
248
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200249 return( (int) len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200250}
251
252/*
253 * Extension ::= SEQUENCE {
254 * extnID OBJECT IDENTIFIER,
255 * critical BOOLEAN DEFAULT FALSE,
256 * extnValue OCTET STRING
257 * -- contains the DER encoding of an ASN.1 value
258 * -- corresponding to the extension type identified
259 * -- by extnID
260 * }
261 */
262int x509_write_extensions( unsigned char **p, unsigned char *start,
263 asn1_named_data *first )
264{
265 int ret;
266 size_t len = 0;
267 asn1_named_data *cur_ext = first;
268
269 while( cur_ext != NULL )
270 {
271 ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
272 cur_ext = cur_ext->next;
273 }
274
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200275 return( (int) len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200276}
277
278#endif /* POLARSSL_X509_CREATE_C */