blob: b59abbfe8d0ca9e1b79dff10c6482ad649cfcc7c [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
34int x509write_string_to_names( asn1_named_data **head, char *name )
35{
36 int ret = 0;
37 char *s = name, *c = s;
38 char *end = s + strlen( s );
39 char *oid = NULL;
40 int in_tag = 1;
41 asn1_named_data *cur;
42
43 /* Clear existing chain if present */
44 asn1_free_named_data_list( head );
45
46 while( c <= end )
47 {
48 if( in_tag && *c == '=' )
49 {
50 if( memcmp( s, "CN", 2 ) == 0 && c - s == 2 )
51 oid = OID_AT_CN;
52 else if( memcmp( s, "C", 1 ) == 0 && c - s == 1 )
53 oid = OID_AT_COUNTRY;
54 else if( memcmp( s, "O", 1 ) == 0 && c - s == 1 )
55 oid = OID_AT_ORGANIZATION;
56 else if( memcmp( s, "L", 1 ) == 0 && c - s == 1 )
57 oid = OID_AT_LOCALITY;
58 else if( memcmp( s, "R", 1 ) == 0 && c - s == 1 )
59 oid = OID_PKCS9_EMAIL;
60 else if( memcmp( s, "OU", 2 ) == 0 && c - s == 2 )
61 oid = OID_AT_ORG_UNIT;
62 else if( memcmp( s, "ST", 2 ) == 0 && c - s == 2 )
63 oid = OID_AT_STATE;
64 else
65 {
Paul Bakker51876562013-09-17 14:36:05 +020066 ret = POLARSSL_ERR_X509_UNKNOWN_OID;
Paul Bakker7c6b2c32013-09-16 13:49:26 +020067 goto exit;
68 }
69
70 s = c + 1;
71 in_tag = 0;
72 }
73
74 if( !in_tag && ( *c == ',' || c == end ) )
75 {
76 if( ( cur = asn1_store_named_data( head, oid, strlen( oid ),
77 (unsigned char *) s,
78 c - s ) ) == NULL )
79 {
Paul Bakker51876562013-09-17 14:36:05 +020080 return( POLARSSL_ERR_X509_MALLOC_FAILED );
Paul Bakker7c6b2c32013-09-16 13:49:26 +020081 }
82
83 while( c < end && *(c + 1) == ' ' )
84 c++;
85
86 s = c + 1;
87 in_tag = 1;
88 }
89 c++;
90 }
91
92exit:
93
94 return( ret );
95}
96
97/* The first byte of the value in the asn1_named_data structure is reserved
98 * to store the critical boolean for us
99 */
100int x509_set_extension( asn1_named_data **head, const char *oid, size_t oid_len,
101 int critical, const unsigned char *val, size_t val_len )
102{
103 asn1_named_data *cur;
104
105 if( ( cur = asn1_store_named_data( head, oid, oid_len,
106 NULL, val_len + 1 ) ) == NULL )
107 {
Paul Bakker51876562013-09-17 14:36:05 +0200108 return( POLARSSL_ERR_X509_MALLOC_FAILED );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200109 }
110
111 cur->val.p[0] = critical;
112 memcpy( cur->val.p + 1, val, val_len );
113
114 return( 0 );
115}
116
117/*
118 * RelativeDistinguishedName ::=
119 * SET OF AttributeTypeAndValue
120 *
121 * AttributeTypeAndValue ::= SEQUENCE {
122 * type AttributeType,
123 * value AttributeValue }
124 *
125 * AttributeType ::= OBJECT IDENTIFIER
126 *
127 * AttributeValue ::= ANY DEFINED BY AttributeType
128 */
129static int x509_write_name( unsigned char **p, unsigned char *start,
130 const char *oid, size_t oid_len,
131 const unsigned char *name, size_t name_len )
132{
133 int ret;
134 size_t len = 0;
135
136 // Write PrintableString for all except OID_PKCS9_EMAIL
137 //
138 if( OID_SIZE( OID_PKCS9_EMAIL ) == oid_len &&
139 memcmp( oid, OID_PKCS9_EMAIL, oid_len ) == 0 )
140 {
141 ASN1_CHK_ADD( len, asn1_write_ia5_string( p, start,
142 (const char *) name,
143 name_len ) );
144 }
145 else
146 {
147 ASN1_CHK_ADD( len, asn1_write_printable_string( p, start,
148 (const char *) name,
149 name_len ) );
150 }
151
152 // Write OID
153 //
154 ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
155
156 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
157 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
158
159 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
160 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) );
161
162 return( len );
163}
164
165int x509_write_names( unsigned char **p, unsigned char *start,
166 asn1_named_data *first )
167{
168 int ret;
169 size_t len = 0;
170 asn1_named_data *cur = first;
171
172 while( cur != NULL )
173 {
174 ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p,
175 cur->oid.len,
176 cur->val.p, cur->val.len ) );
177 cur = cur->next;
178 }
179
180 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
181 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
182
183 return( len );
184}
185
186int x509_write_sig( unsigned char **p, unsigned char *start,
187 const char *oid, size_t oid_len,
188 unsigned char *sig, size_t size )
189{
190 int ret;
191 size_t len = 0;
192
193 if( *p - start < (int) size + 1 )
194 return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
195
196 len = size;
197 (*p) -= len;
198 memcpy( *p, sig, len );
199
200 *--(*p) = 0;
201 len += 1;
202
203 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
204 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
205
206 // Write OID
207 //
208 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid,
209 oid_len, 0 ) );
210
211 return( len );
212}
213
214static int x509_write_extension( unsigned char **p, unsigned char *start,
215 asn1_named_data *ext )
216{
217 int ret;
218 size_t len = 0;
219
220 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->val.p + 1,
221 ext->val.len - 1 ) );
222 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->val.len - 1 ) );
223 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) );
224
225 if( ext->val.p[0] != 0 )
226 {
227 ASN1_CHK_ADD( len, asn1_write_bool( p, start, 1 ) );
228 }
229
230 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->oid.p,
231 ext->oid.len ) );
232 ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->oid.len ) );
233 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) );
234
235 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
236 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
237
238 return( len );
239}
240
241/*
242 * Extension ::= SEQUENCE {
243 * extnID OBJECT IDENTIFIER,
244 * critical BOOLEAN DEFAULT FALSE,
245 * extnValue OCTET STRING
246 * -- contains the DER encoding of an ASN.1 value
247 * -- corresponding to the extension type identified
248 * -- by extnID
249 * }
250 */
251int x509_write_extensions( unsigned char **p, unsigned char *start,
252 asn1_named_data *first )
253{
254 int ret;
255 size_t len = 0;
256 asn1_named_data *cur_ext = first;
257
258 while( cur_ext != NULL )
259 {
260 ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
261 cur_ext = cur_ext->next;
262 }
263
264 return( len );
265}
266
267#endif /* POLARSSL_X509_CREATE_C */