blob: 7637e61712d81c3b7bc1a3323cd4b46afe80dd57 [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;
Paul Bakker7c6b2c32013-09-16 13:49:26 +020046
47 /* Clear existing chain if present */
48 asn1_free_named_data_list( head );
49
50 while( c <= end )
51 {
52 if( in_tag && *c == '=' )
53 {
Paul Bakker7b0be682013-10-29 14:24:37 +010054 if( c - s == 2 && strncasecmp( s, "CN", 2 ) == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020055 oid = OID_AT_CN;
Paul Bakker7b0be682013-10-29 14:24:37 +010056 else if( c - s == 1 && strncasecmp( s, "C", 1 ) == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020057 oid = OID_AT_COUNTRY;
Paul Bakker7b0be682013-10-29 14:24:37 +010058 else if( c - s == 1 && strncasecmp( s, "O", 1 ) == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020059 oid = OID_AT_ORGANIZATION;
Paul Bakker7b0be682013-10-29 14:24:37 +010060 else if( c - s == 1 && strncasecmp( s, "L", 1 ) == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020061 oid = OID_AT_LOCALITY;
Paul Bakker7b0be682013-10-29 14:24:37 +010062 else if( c - s == 1 && strncasecmp( s, "R", 1 ) == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020063 oid = OID_PKCS9_EMAIL;
Paul Bakker7b0be682013-10-29 14:24:37 +010064 else if( c - s == 2 && strncasecmp( s, "OU", 2 ) == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020065 oid = OID_AT_ORG_UNIT;
Paul Bakker7b0be682013-10-29 14:24:37 +010066 else if( c - s == 2 && strncasecmp( s, "ST", 2 ) == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020067 oid = OID_AT_STATE;
Paul Bakker0767e672014-04-18 14:11:37 +020068 else if( c - s == 12 && strncasecmp( s, "emailAddress", 12 ) == 0 )
69 oid = OID_PKCS9_EMAIL;
Paul Bakker7b0be682013-10-29 14:24:37 +010070 else if( c - s == 12 && strncasecmp( s, "serialNumber", 12 ) == 0 )
71 oid = OID_AT_SERIAL_NUMBER;
72 else if( c - s == 13 && strncasecmp( s, "postalAddress", 13 ) == 0 )
73 oid = OID_AT_POSTAL_ADDRESS;
74 else if( c - s == 10 && strncasecmp( s, "postalCode", 10 ) == 0 )
75 oid = OID_AT_POSTAL_CODE;
Paul Bakker7c6b2c32013-09-16 13:49:26 +020076 else
77 {
Paul Bakker51876562013-09-17 14:36:05 +020078 ret = POLARSSL_ERR_X509_UNKNOWN_OID;
Paul Bakker7c6b2c32013-09-16 13:49:26 +020079 goto exit;
80 }
81
82 s = c + 1;
83 in_tag = 0;
84 }
85
86 if( !in_tag && ( *c == ',' || c == end ) )
87 {
Paul Bakkera9c16d22014-04-17 12:42:18 +020088 if( asn1_store_named_data( head, oid, strlen( oid ),
89 (unsigned char *) s,
90 c - s ) == NULL )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020091 {
Paul Bakker51876562013-09-17 14:36:05 +020092 return( POLARSSL_ERR_X509_MALLOC_FAILED );
Paul Bakker7c6b2c32013-09-16 13:49:26 +020093 }
94
95 while( c < end && *(c + 1) == ' ' )
96 c++;
97
98 s = c + 1;
99 in_tag = 1;
100 }
101 c++;
102 }
103
104exit:
105
106 return( ret );
107}
108
109/* The first byte of the value in the asn1_named_data structure is reserved
110 * to store the critical boolean for us
111 */
112int x509_set_extension( asn1_named_data **head, const char *oid, size_t oid_len,
113 int critical, const unsigned char *val, size_t val_len )
114{
115 asn1_named_data *cur;
116
117 if( ( cur = asn1_store_named_data( head, oid, oid_len,
118 NULL, val_len + 1 ) ) == NULL )
119 {
Paul Bakker51876562013-09-17 14:36:05 +0200120 return( POLARSSL_ERR_X509_MALLOC_FAILED );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200121 }
122
123 cur->val.p[0] = critical;
124 memcpy( cur->val.p + 1, val, val_len );
125
126 return( 0 );
127}
128
129/*
130 * RelativeDistinguishedName ::=
131 * SET OF AttributeTypeAndValue
132 *
133 * AttributeTypeAndValue ::= SEQUENCE {
134 * type AttributeType,
135 * value AttributeValue }
136 *
137 * AttributeType ::= OBJECT IDENTIFIER
138 *
139 * AttributeValue ::= ANY DEFINED BY AttributeType
140 */
141static int x509_write_name( unsigned char **p, unsigned char *start,
142 const char *oid, size_t oid_len,
143 const unsigned char *name, size_t name_len )
144{
145 int ret;
146 size_t len = 0;
147
148 // Write PrintableString for all except OID_PKCS9_EMAIL
149 //
150 if( OID_SIZE( OID_PKCS9_EMAIL ) == oid_len &&
151 memcmp( oid, OID_PKCS9_EMAIL, oid_len ) == 0 )
152 {
153 ASN1_CHK_ADD( len, asn1_write_ia5_string( p, start,
154 (const char *) name,
155 name_len ) );
156 }
157 else
158 {
159 ASN1_CHK_ADD( len, asn1_write_printable_string( p, start,
160 (const char *) name,
161 name_len ) );
162 }
163
164 // Write OID
165 //
166 ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
167
168 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
169 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
170
171 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
172 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) );
173
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200174 return( (int) len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200175}
176
177int x509_write_names( unsigned char **p, unsigned char *start,
178 asn1_named_data *first )
179{
180 int ret;
181 size_t len = 0;
182 asn1_named_data *cur = first;
183
184 while( cur != NULL )
185 {
186 ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p,
187 cur->oid.len,
188 cur->val.p, cur->val.len ) );
189 cur = cur->next;
190 }
191
192 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
193 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
194
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200195 return( (int) len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200196}
197
198int x509_write_sig( unsigned char **p, unsigned char *start,
199 const char *oid, size_t oid_len,
200 unsigned char *sig, size_t size )
201{
202 int ret;
203 size_t len = 0;
204
205 if( *p - start < (int) size + 1 )
206 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
207
208 len = size;
209 (*p) -= len;
210 memcpy( *p, sig, len );
211
212 *--(*p) = 0;
213 len += 1;
214
215 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
216 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
217
218 // Write OID
219 //
220 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid,
221 oid_len, 0 ) );
222
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200223 return( (int) len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200224}
225
226static int x509_write_extension( unsigned char **p, unsigned char *start,
227 asn1_named_data *ext )
228{
229 int ret;
230 size_t len = 0;
231
232 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->val.p + 1,
233 ext->val.len - 1 ) );
234 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->val.len - 1 ) );
235 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) );
236
237 if( ext->val.p[0] != 0 )
238 {
239 ASN1_CHK_ADD( len, asn1_write_bool( p, start, 1 ) );
240 }
241
242 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->oid.p,
243 ext->oid.len ) );
244 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->oid.len ) );
245 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) );
246
247 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
248 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
249
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200250 return( (int) len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200251}
252
253/*
254 * Extension ::= SEQUENCE {
255 * extnID OBJECT IDENTIFIER,
256 * critical BOOLEAN DEFAULT FALSE,
257 * extnValue OCTET STRING
258 * -- contains the DER encoding of an ASN.1 value
259 * -- corresponding to the extension type identified
260 * -- by extnID
261 * }
262 */
263int x509_write_extensions( unsigned char **p, unsigned char *start,
264 asn1_named_data *first )
265{
266 int ret;
267 size_t len = 0;
268 asn1_named_data *cur_ext = first;
269
270 while( cur_ext != NULL )
271 {
272 ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
273 cur_ext = cur_ext->next;
274 }
275
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200276 return( (int) len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200277}
278
279#endif /* POLARSSL_X509_CREATE_C */